标签:
Unity是一个轻量级的可扩展的依赖注入容器,支持构造函数,属性和方法调用注入。在Nuget里安装unity
UnityContainer.RegisterType<ITFrom,TTO>(); //注册映射
UnityContainer.RegisterType< ITFrom, TTO >("keyName");//注册映射指定key值
IEnumerable<T> databases = UnityContainer.ResolveAll<T>(); //返回所有注册同一个接口的实例对象
IT instance = UnityContainer.Resolve<IT>(); //返回最后一个注册同一个接口的实例对象,每次都是创建新的对象
T instance = UnityContainer.Resolve<T>("keyName");//根据key值获取指定的实例对象,每次都是创建新的对象
UnitContainer.RegisterInstance<T>("keyName",new T()); //单例模式,指定key值,获取同一个实例对象
UnityContainer.BuildUp(existingInstance);
IUnityContainer childContainer1 = parentContainer.CreateChildContainer();
1.演示的是container.Resolve<T>()创建T类型,而T是否已经注册过了,没注册过的就会尝试去创建T类型,在创建T类型的构造函数时,如果需要传递参数,也要涉及到参数是否注册过的问题
定义日志接口
public interface ILogger { void Write(string log); } public class FileLogger:ILogger { public void Write(string log) { Console.WriteLine("输出日志到文件!"); } } public class ConsoleLogger : ILogger { public void Write(string log) { Console.WriteLine("输出日志到控制台!"); } }
定义数据库类
public class Database { } public class CustomerDatabase : Database { private ILogger _logger; public CustomerDatabase(ILogger logger) { _logger = logger; } public void Write(string log)
{
_logger.Write(log);
} }
static void Main(string[] args) { //实例化Unity容器 UnityContainer container = new UnityContainer(); //注册类型映射 container.RegisterType<ILogger, FileLogger>(); container.RegisterType<ILogger, ConsoleLogger>(); //使用Resolve方法创建我们定义好的CustomerDatabase类型,如果在容器中没有注册的类型。执行Resolv方法后,Unity尝试创建该类型,会执行该类的构造器 // public CustomerDatabase(ILogger logger)的构造函数需要传递一个日志接口实例,它默认传递上面最后注册的ConsoleLogger实例 CustomerDatabase database = container.Resolve<CustomerDatabase>(); database.Write("qqq"); Console.ReadKey(); }
2.演示的是创建注册过的实例,并且返回的是新对象
static void Main(string[] args) { UnityContainer container = new UnityContainer(); container.RegisterType<ILogger, FileLogger>(); ILogger logger = container.Resolve<ILogger>(); ILogger logger2 = container.Resolve<ILogger>(); Console.WriteLine(object.ReferenceEquals(logger,logger2)); Console.ReadKey(); }
输出的是false,是不同的对象,说明每次调用container.Resolve<ILogger>()返回的是新的FileLogger对象
3.演示的是每次返回的都是同一个对象,不要例如2创建不同的对象,就像单例模式,RegisterType方法包含一个重载,将使用 new ContainerControlledLifetimeManager()
static void Main(string[] args) { UnityContainer container = new UnityContainer(); container.RegisterType<ILogger, FileLogger>(); container.RegisterType<Database, CustomerDatabase> (new ContainerControlledLifetimeManager()); CustomerDatabase bs1 = container.Resolve<CustomerDatabase>(); CustomerDatabase bs2 = container.Resolve<CustomerDatabase>(); Console.WriteLine(object.ReferenceEquals(bs1, bs2)); Console.ReadKey(); }
4.如果类似例子1,注册同一个接口的不同实例 ,使用 container.Resolve<ILogger>();只是返回最后一个注册的ConsoleLogger实例,改进在我们向容器里注册时,可以附带一个string 类型的Key值。可以使用key值获取指定的实例对象
//注册类型映射,同一个接口的不同实例 container.RegisterType<ILogger, FileLogger>(); container.RegisterType<ILogger, ConsoleLogger>();
使用 container.Resolve<ILogger>();只是返回最后一个注册的ConsoleLogger实例
ILogger logger2 = container.Resolve<ILogger>();
改进如下:
再创建两个数据库类
public class SQLDatabase:Database { } public class ORACLEDatabase:Database { }
使用key获取指定的数据库实例对象
static void Main(string[] args) { UnityContainer container = new UnityContainer(); container.RegisterType<Database, SQLDatabase>("SQL"); container.RegisterType<Database, ORACLEDatabase>("ORACLE"); //返回所有的实例 IEnumerable<Database> databases = container.ResolveAll<Database>(); //根据key返回指定的SQL数据库实例 Database database = container.Resolve<Database>("SQL"); }
5.使用RegisterInstance注册传入的实例,后面再调用Resolve就会像例子3一样返回同一个实例对象
static void Main(string[] args) { UnityContainer container = new UnityContainer(); container.RegisterInstance<Database>(new SQLDatabase()); container.RegisterInstance<Database>("Oracle", new ORACLEDatabase()); Database database1 = container.Resolve<Database>(); Database database2 = container.Resolve<Database>(); Database oracleDatabase = container.Resolve<Database>("Oracle"); Console.WriteLine(object.ReferenceEquals(database1, database2)); Console.ReadKey(); }
5.1我们还有一种方法可以把已经存在的实例注入到容器中,这里用到了BuildUp和RegisterInstance,其实我觉得用不用BuildUp都可以了
public class DB2Database:Database { [Dependency] public ILogger Logger { get; set; } }
static void Main(string[] args) { UnityContainer container = new UnityContainer(); container.RegisterType<ILogger, FileLogger>(); DB2Database existDatabase = new DB2Database(); container.BuildUp(existDatabase); container.RegisterInstance<Database>(existDatabase); //DB2Database的属性中Logger上面打了 [Dependency]特性,所以根据这里RegisterType<ILogger, FileLogger>();会默认给DB2Database的Logger属性注入FileLogger Database database1 = container.Resolve<Database>(); Database database2 = container.Resolve<Database>(); Console.WriteLine(object.ReferenceEquals(database1, database2)); Console.ReadKey(); }
1.配置如下
<configuration> <configSections> <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/> </configSections> <unity xmlns="http://schemas.microsoft.com/practices/2010/unity"> <container name="containerOne"> <types> <type type="UnityDemo.ILogger" mapTo="UnityDemo.FileLogger" lifeTime="Singleton"/> </types> </container> </unity> </configuration>
2.读取配置文件
第一种,我们使用configurationManager,引用命名空间System.Configuration
IUnityContainer myContainer = new UnityContainer(); myContainer.LoadConfiguration("containerOne "); UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity"); section.Configure(myContainer, "containerOne");
第二种,我们可以直接用容器读取配置信息
IUnityContainer myContainer = new UnityContainer(); myContainer.LoadConfiguration("containerOne");
public class GenericDatabase:Database { private string _connectionString; public ILogger Logger { get; set; } public GenericDatabase(string connectionString) { _connectionString = connectionString; } }
通过Injection API 来为这个类注入connectionString 和 Logger,首先我们要注册映射关系:
IUnityContainer container = new UnityContainer(); container.RegisterType<ILogger, FileLogger>(); container.RegisterType<Database, GenericDatabase>();
然后通过Injection API 为GenericDatabase注入ConnectionStrings和Logger
container.Configure<InjectedMembers>() .ConfigureInjectionFor<GenericDatabase>( new InjectionConstructor( ConfigurationManager.ConnectionStrings["ConnectionStrings"] == null ? "defaultConnectionString" : ConfigurationManager.ConnectionStrings["ConnectionStrings"].ConnectionString), new InjectionProperty("Logger") ); Database database = container.Resolve<Database>();
这样最后获得的database 就包含了connection 和 Logger
容器是可以嵌套的,获取实例时遵循的规则是,如果子容器里不包含需要的对象,则会去父容器获取。如果有,则从自己里获取。一旦父容器销毁,子容器也随之销毁。
UnityContainer parentContainer = new UnityContainer(); IUnityContainer childContainer1 = parentContainer.CreateChildContainer(); IUnityContainer childContainer2 = parentContainer.CreateChildContainer(); parentContainer.RegisterType<ILogger, FileLogger>(new ContainerControlledLifetimeManager()); childContainer1.RegisterType<ILogger, ConsoleLogger>(new ContainerControlledLifetimeManager()); //子容器childContainer2里面没有注册日志类型,所以从父parentContainer得到FileLogger ILogger logger = childContainer2.Resolve<ILogger>(); logger.Write("qqq"); //子容器childContainer1里面有注册控制台日志,所以从自己本身得到consoleLogger ILogger logger2 = childContainer1.Resolve<ILogger>();
标签:
原文地址:http://www.cnblogs.com/kesimin/p/5039667.html