現如今可能每個人都會在項目中使用著某種 IoC 容器,并且我們的意識中已經形成一些固定的使用模式,有時會很難想象如果沒有 IoC 容器工作該怎么進展。
IoC 容器通過某種特定設計的配置,用于在運行時決定將哪些組件注入到我們的代碼中。這種配置可以是基于 XML 的映射,也可以是基于 Fluent API 的設計。但隨著項目代碼的不斷增長,配置文件總是變得越來越冗長。此時,我們該尋求某種改進措施來增強代碼的可讀性和可維護性。
對于 IoC 容器來講,自動注冊機制是一項非常實用的功能,并且其在某些特定的場景下特別的有效。
Unity 是微軟提供的依賴注入容器,其在 2.0 版本時并不支持自動注冊機制(Auto Registration),在 3.0 版本中添加了基于約定的自動注冊機制(Registration By Convention)。
Codeplex 中的 Unity Auto Registration 項目通過使用 Fluent API 方式為 Unity 擴展了自動注冊機制。
我們可以通過 NuGet 來添加 Unity Auto Registration 包引用。
PM> Install-Package UnityAutoRegistration
1 PM> Install-Package UnityAutoRegistration 2 Attempting to resolve dependency 'Unity (≥ 2.1.505.0)'. 3 Attempting to resolve dependency 'CommonServiceLocator (≥ 1.0)'. 4 Successfully installed 'CommonServiceLocator 1.0'. 5 You are downloading Unity from Microsoft, the license agreement to which is available at http://www.opensource.org/licenses/ms-pl. Check the package for additional dependencies, which may come with their own license agreement(s). Your use of the package and dependencies constitutes your acceptance of their license agreements. If you do not accept the license agreement(s), then delete the relevant components from your device. 6 Successfully installed 'Unity 2.1.505.2'. 7 You are downloading UnityAutoRegistration from agovorov, the license agreement to which is available at http://autoregistration.codeplex.com/license. Check the package for additional dependencies, which may come with their own license agreement(s). Your use of the package and dependencies constitutes your acceptance of their license agreements. If you do not accept the license agreement(s), then delete the relevant components from your device. 8 Successfully installed 'UnityAutoRegistration 1.0.0.2'. 9 Successfully added 'CommonServiceLocator 1.0' to ConsoleApplication13_UnityAutoRegistration. 10 Successfully added 'Unity 2.1.505.2' to ConsoleApplication13_UnityAutoRegistration. 11 Successfully added 'UnityAutoRegistration 1.0.0.2' to ConsoleApplication13_UnityAutoRegistration.
Unity Auto Registration 通過使用較少的代碼進行配置,自動加載、搜索和匹配指定程序集中的類和接口,并形成映射注冊到 Unity 中。
1 using System; 2 using Microsoft.Practices.Unity; 3 using Unity.AutoRegistration; 4 5 namespace ConsoleApplication13_UnityAutoRegistration 6 { 7 class Program 8 { 9 static void Main(string[] args) 10 { 11 IUnityContainer container = new UnityContainer(); 12 13 container 14 .ConfigureAutoRegistration() 15 .ExcludeSystemAssemblies() 16 .Include(type => type.ImplementsOpenGeneric(typeof(ICommandHandler<>)), 17 Then.Register().AsFirstInterfaceOfType().WithTypeName()) 18 .ApplyAutoRegistration(); 19 20 container 21 .ConfigureAutoRegistration() 22 .LoadAssemblyFrom(typeof(IRepository<>).Assembly.Location) 23 .ExcludeSystemAssemblies() 24 .Exclude(type => type.Name.Contains("_Proxy_")) 25 .Exclude(type => type.Name.EndsWith("_Accessor", StringComparison.Ordinal)) 26 .Include(type => type.Implements<IBaseProvider>(), Then.Register().WithName(type => "SampleProvider")) 27 .Exclude(type => type.Name == "IBaseProvider") 28 .ApplyAutoRegistration(); 29 30 container 31 .ConfigureAutoRegistration() 32 .ExcludeAssemblies(a => a.GetName().FullName.Contains("Test")) 33 .Include(If.Implements<ILogger>, Then.Register().UsingPerCallMode()) 34 .Include(If.ImplementsITypeName, Then.Register().WithTypeName()) 35 .Include(If.Implements<ICustomerRepository>, Then.Register().WithName("SampleRepository")) 36 .Include(If.Implements<IOrderManager>, 37 Then.Register() 38 .AsSingleInterfaceOfType() 39 .UsingPerCallMode()) 40 .Include(If.DecoratedWith<LoggerAttribute>, 41 Then.Register() 42 .As<IDisposable>() 43 .WithTypeName() 44 .UsingLifetime<ContainerControlledLifetimeManager>()) 45 .Exclude(t => t.Name.Contains("Trace")) 46 .ApplyAutoRegistration(); 47 48 Console.ReadKey(); 49 } 50 } 51 52 [AttributeUsage(AttributeTargets.Class)] 53 public class LoggerAttribute : Attribute { } 54 public interface ILogger { } 55 [LoggerAttribute] 56 public class MockLogger : ILogger, IDisposable { public void Dispose() { } } 57 public interface IBaseProvider { } 58 public interface IRepository<T> { } 59 public interface ICustomerRepository : IRepository<Customer> { } 60 public class CustomerRepository : ICustomerRepository { } 61 public interface IOrderManager { } 62 public class OrderManager : IOrderManager { } 63 public class Customer { } 64 public class Order { } 65 public interface ICommandHandler<T> { } 66 public class CommandHandler<T> : ICommandHandler<T> { } 67 }
所以如何你仍然需要使用 Unity 2.0/2.1 版本來管理依賴注入的配置,推薦使用 Unity Auto Registration 。
文章列表