Prism的依赖注入支持Unity,但不仅限于Unity,Prism通过IServiceLocator来构造对象,定义如下
IServiceLocatorpublic interface IServiceLocator : IServiceProvider { object GetInstance(Type serviceType); object GetInstance(Type serviceType, string key); IEnumerable<object> GetAllInstances(Type serviceType); TService GetInstance<TService>(); TService GetInstance<TService>(string key); IEnumerable<TService> GetAllInstances<TService>(); }
还有一个IServiceLocator的扩展类
ServiceLocatorExtensions public static class ServiceLocatorExtensions { public static object TryResolve(this IServiceLocator locator, Type type) { try { return locator.GetInstance(type); } catch (ActivationException) { return null; } } public static T TryResolve<T>(this IServiceLocator locator) where T: class { return locator.TryResolve(typeof(T)) as T; } }
默认为我们提供了,UnityServiceLocatorAdaper,看名字就知道它是一个适配器,用来连接Unity和IServiceLocator,
UnityServiceLocatorAdapterpublic class UnityServiceLocatorAdapter : ServiceLocatorImplBase { private readonly IUnityContainer _unityContainer; public UnityServiceLocatorAdapter(IUnityContainer unityContainer) { _unityContainer = unityContainer; } protected override object DoGetInstance(Type serviceType, string key) { return _unityContainer.Resolve(serviceType, key); } protected override IEnumerable<object> DoGetAllInstances(Type serviceType) { return _unityContainer.ResolveAll(serviceType); } }
UnityServiceLocatorAdapter的定义出人意料的简单,仅仅二个方法,它继承自Microsoft.Practices.ServiceLocation.dll里的ServiceLocatorImplBase,
这个类的定义也是非常简单,里面的代码仅仅是将对方法的调用委托给DoGetInstance和DoGetAllInstances这二个虚方法,代码很精简,在UnityBootstraper里通过UnityContainer来获取UnityServiceLocatorAdaper,再由UnityServiceLocatorAdaper取得各种服务。在UnityBootstrapper里通过调用
RegisterTypeIfMissing(typeof(IServiceLocator), typeof(UnityServiceLocatorAdapter), true);
接下来我们就可以能过serviceLocator来使用Unity提供的依赖注入功能。
如果我们要护展使用第三方的依赖注入容器,就可以通过继承ServiceLocatorImplBase,重写他拉两个虚方法,然后实现我们自定义的Bootstrapper,下面是MefServiceLocatorAdaper的实现代码
UnityServiceLocatorAdapter public class MefServiceLocatorAdapter : ServiceLocatorImplBase { private readonly CompositionContainer compositionContainer; public MefServiceLocatorAdapter(CompositionContainer compositionContainer) { this.compositionContainer = compositionContainer; } protected override IEnumerable<object> DoGetAllInstances(Type serviceType) { List<object> instances = new List<object>(); IEnumerable<Lazy<object, object>> exports = this.compositionContainer.GetExports(serviceType, null, null); if (exports != null) { instances.AddRange(exports.Select(export => export.Value)); } return instances; } protected override object DoGetInstance(Type serviceType, string key) { IEnumerable<Lazy<object, object>> exports = this.compositionContainer.GetExports(serviceType, null, key); if ((exports != null) && (exports.Count() > 0)) { return exports.Single().Value; } throw new ActivationException( this.FormatActivationExceptionMessage(new CompositionException("Export not found"), serviceType, key)); } }
是不是也很简单呀