使用Unity解耦你的系统—PART2——了解Unity的使用方法(1)
使用Unity解耦你的系统—PART2——了解Unity的使用方法(2)
使用Unity解耦你的系统—PART2——了解Unity的使用方法(3)
download《Unity Instructions CS.pdf》
IUnityContainer container = new UnityContainer()
// Register 映射。
<configSections> <section name=”unity” type=”Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration”/> </configSections>
<unity xmlns=”http://schemas.microsoft.com/practices/2010/unity”>
? <alias alias=”IClass” type=”UnityStudyConsole.IDemo.IClass, UnityStudyConsole” />??
? <container name=”First”>
??? <register type=”IClass” mapTo=”MyClass” />
? </container>
</unity>
IUnityContainer container = new UnityContainer();
// 使用LoadConfiguration默认使用unity section加载unity(无名字)节点。
container.LoadConfiguration();
// 获取section,加载有名字的unity配置。
UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection(“unity”);
container.LoadConfiguration(section, “First”);
参考:
Using Design-Time Configuration
container .RegisterType<IStocksTickerView, StocksTickerForm>() .RegisterType<IStockQuoteService, MoneyCentralStockQuoteService>();
注:使用RegisterType注册的默认生命周期为transient lifetime(每次使用Resolve或者ResolveAll或者属性注入的时候都实例化一个新实例)。
// 注册实例,“UI”为实例名。
RegisterInstance(new TraceSource(“UI”, SourceLevels.All));
// 注册接口与实例的映射(MySingleton为映射名)
myContainer.RegisterInstance<IMyObject>(“MySingleton”, MyRealObject);
// 注册带有生命周期的接口与实例的映射。
myContainer.RegisterInstance<IMyObject>(“MySingleton”, MyRealObject, new ContainerControlledLifetimeManager());
注:使用RegisterInstance注册的实例的生命周期为ContainerControlledLifetimeManager;使用该方法无法为实例制定TransientLifetimeManager生命周期,否则会产生异常。
[Dependency]
public ILogger Logger?
{?
get { return logger; }?
set { logger = value; }?
}
RegisterType<ILogger, ConsoleLogger>();
使用带有名字的的属性注入,如:
[Dependency(“UI”)]
public ILogger Logger?
{?
get { return logger; }?
set { logger = value; }?
}
注册带有名字的Logger,如:
RegisterType<ILogger, TraceSourceLogger>(“UI”);
注册不带名字的属性
RegisterType<IStockQuoteService, MoneyCentralStockQuoteService>( new InjectionProperty(“Logger”))
注:其中Logger为MoneyCentralStockQuoteService类中的一个类型为ILogger的属性。
注入带有名字的属性:
RegisterType<StocksTickerPresenter>( new InjectionProperty(“Logger”, new ResolvedParameter<ILogger>(“UI”)));
注:其中new InjectionProperty第二参数是指示要解析一个名字为“UI”的ILogger。
注册多个属性:
//注册对象关系时初始化对象的属性 container.RegisterType<IClass, MyClass>( new InjectionProperty("Name", "A班"), new InjectionProperty("Description", "A班的描述"));
重载调用:
//var myClass = container.Resolve<IClass>(new PropertyOverride
// ("Name", "重载后的A班"), // new PropertyOverride("Description", "重载后的A班的描述")); var myClass = container.Resolve<IClass>(new PropertyOverrides() { {"Name","重载后的A班"}, {"Description","重载后的A班的描述"} }.OnType<MyClass>());
注意:The PropertyOverride is not limited to a single type,
so it will apply to all resolved objects with a “Logger” property.
参考:本篇中的构造函数注入
[InjectionConstructor]
RegisterType<ILogger, TraceSourceLogger>( “UI”, new InjectionConstructor(“UI”))
注:其中第一个参数“UI”为ILogger, TraceSourceLogger的映射名,第二个参数new InjectionConstructor(“UI”)为构造函数传入一个字符串类型的参数“UI”。如此,TraceSourceLogger将调用一个带有string类型的构造函数。
使用这个API注入比用“InjectionConstructor”标注的构造函数的优先级别更高。
如:
container.RegisterType<IClass, YourClass>( new InjectionConstructor("my", new MyClass())); container.Resolve<IClass>();
在调用的时候我们想更换原先注册的值,可以通过ParameterOverride和ParameterOverrides
来实现,其中ParameterOverride是针对一个参数,而ParameterOverrides是针对参数列表:
// 在使用ParameterOverrides进行重载参数时,
// 可以使用如上面代码的方式进行指定,但是同样需要使用OnType来指定,
// 不过这个的OnType指定的类型是注册的对象类型。
container.Resolve<IClass>(new ParameterOverrides() { {"test","test"}, {"my",new MyClass()} }.OnType<YourClass>());// 在使用ParameterOverride方法来重载参数时,如果注册的参数是一个
// 具体的对象就需要使用OnType这个扩展方法来指定对应的类型,否则会报错。
container.Resolve<IClass>(new ParameterOverride("test", "test"),new ParameterOverride("my", "new MyClass").OnType<MyClass>());
Unity还为我们提供了一个DependencyOverride重载,其使用方法和参数重载、属性重载类似,这边就不演示了,不过需要注意的是DependencyOverride是针对所注册对象类型中所包含的对象类型重载,例如在A类中有构造函数参数是B类,同时也有个属性依赖于B类,当使用了DependencyOverride后,这个A对象原先注册的有关B类的依赖将全部改变。
container .RegisterType( typeof(IRepository<>), typeof(ValidatingRepository<>), “validating”);
注意:open generic types cannot be used as generic type arguments。
可以在开闭泛型之间建立映射,也可以在闭映射和非泛型之间建立映射,如:
RegisterType<IValidator<StockQuote>, RandomStockQuoteValidator>();
使用overrides解析泛型:
StocksTickerPresenter presenter = container.Resolve<StocksTickerPresenter>( new ParameterOverride( “repository”, new ResolvedParameter<IRepository<StockQuote>>(“validating”)) .OnType<StocksTickerPresenter>());
闭泛型
<register type=”IRepository[StockQuote]” mapTo=”DebugRepository[StockQuote]“/>
开泛型
<register type=”IRepository[]” mapTo=”DebugRepository[]“/>
例:
<register type=”IRepository[]” mapTo=”DebugRepository[]“/>
public StocksTickerPresenter( IStocksTickerView view, IStockQuoteService stockQuoteService,?IRepository<StockQuote> repository) { … }
解析IRepository<StockQuote>过程:首先查找是否有相应的闭泛型,如果有,则进一步解析构造函数,…;如果没有,则查找开泛型,IRepository<>被找到,此时,开泛型DebugRepository<>被使用,StockQuote被传作泛型参数,解析完毕。
CompositeLogger的构造函数为:
public CompositeLogger(ILogger[] loggers)
??????? {
??????????? this.loggers = (IEnumerable<ILogger>)loggers.Clone();
??????? }
注册方法为:
RegisterType<ILogger, CompositeLogger>( “composite”, new InjectionConstructor( new ResolvedArrayParameter<ILogger>( typeof(ILogger), new ResolvedParameter<ILogger>(“UI”))));
其中:第一个参数typeof(ILogger是new ResolvedParameter<ILogger>())的简写。
注意:当解析Array时,只有有名字的实例会被包含进来。
StocksTickerPresenter presenter = container.Resolve<StocksTickerPresenter>();
注:如果StocksTickerPresenter的构造函数有参数,则需要先注册参数。
public static void DeferringResolve() { var resolver = container.Resolve<Func<IClass>>(); //注册IClass与MyClass之间的关系 container.RegisterType<IClass, MyClass>(); //获取MyClass实例 var myClass = resolver(); var resolver2 = container.Resolve<Func<IEnumerable<IClass>>>(); //注册与IClass相关的对象。 container.RegisterType<IClass, MyClass>("my"); container.RegisterType<IClass, YourClass>("your"); //获取与IClass关联的所有命名实例 var classList = resolver2(); }
public static void DisplayContainerRegistrations(IUnityContainer theContainer) { string regName, regType, mapTo, lifetime; Console.WriteLine("容器中 {0} 个注册信息:", theContainer.Registrations.Count()); foreach (ContainerRegistration item in theContainer.Registrations) { regType = item.RegisteredType.Name; mapTo = item.MappedToType.Name; regName = item.Name ?? "[默认]"; lifetime = item.LifetimeManagerType.Name; if (mapTo != regType) { mapTo = " -> " + mapTo; } else { mapTo = string.Empty; } lifetime = lifetime.Substring(0, lifetime.Length -"生命周期管理器".Length); Console.WriteLine("+ {0}{1} '{2}' {3}", regType, mapTo,regName, lifetime); } }
RegisterType<ILogger, TraceSourceLogger>( “UI”, new ContainerControlledLifetimeManager(), new InjectionConstructor(“UI”))
<register type="IClass" mapTo="MyClass"> <lifetime type="transient" /> <!--<lifetime type="SessionLifetimeManager" value="Session#1" typeConverter="SessionLifetimeConverter" />--> </register><br>
?
GC.Collect();
配置文件如下:
<register type=”IClass” mapTo=”MyClass” name=”ccl”>
<lifetime type=”external” />
</register>
<register type=”IClass” mapTo=”MyClass” name=”ccl”>
<lifetime type=”perthread” />
</register>
<register type=”IClass” mapTo=”MyClass” name=”ccl”>
<lifetime type=”transient” />
</register>
<register type="IClass" mapTo="MyClass" name="hl"> <lifetime type="hierarchical"> </register>?
{ [Dependency] public IPresenter Presenter { get; set; } } public class MockPresenter : IPresenter { [Dependency] public IView View { get; set; } } 解析IView得到的实例Presenter 中的View与第一次解析IView的实例为同一个。?