假如你不能改變框架調用定位器的方式,假設框架使用通用服務定位器作爲你的容器和自身之間的界面,你可以添加此功能的自定義IServiceLocator
實現:
// This adapter wraps the CSL LightCoreAdapter of LightCore itself.
public class LightCoreServiceLocatorAdapter : IServiceLocator
{
private readonly LightCoreAdapter container;
public LightCoreServiceLocatorAdapter(IContainer container)
{
// You need a reference to LightCore.CommonServiceLocator.dll.
this.container = new LightCoreAdapter(container);
}
public IEnumerable<TService> GetAllInstances<TService>()
{
return this.container.GetAllInstances<TService>();
}
public IEnumerable<object> GetAllInstances(Type serviceType)
{
return this.container.GetAllInstances(serviceType);
}
public TService GetInstance<TService>(string key)
{
if (key == null)
{
return this.container.GetInstance<TService>(null);
}
else
{
// This is custom logic
this.container.GetInstance<INamedFactory<TService>>().GetByKey(key);
}
}
public TService GetInstance<TService>()
{
return this.container.GetInstance<TService>();
}
public object GetInstance(Type serviceType, string key)
{
if (key == null)
{
return this.container.GetInstance(serviceType);
}
else
{
// This is custom logic
var facType = typeof(INamedFactory<>).MakeGenericType(serviceType);
var factory = (INamedFactory)this.container.GetInstance(facType);
return factory.GetByKey(key);
}
}
public object GetInstance(Type serviceType)
{
return this.container.GetInstance(serviceType);
}
object IServiceProvider.GetService(Type serviceType)
{
((IServiceProvider)this.container).GetService(serviceType);
}
}
此類使用以下兩種自定義接口:
public interface INamedFactory
{
object GetByKey(string key);
}
public interface INamedFactory<T> : INamedFactory
{
T GetByKey(string key);
}
使用這種定製LightCoreServiceLocatorAdapter
這兩個自定義界面,您可以創建自定義的工廠,比如這個通用之一:
public sealed class NamedDelegateFactory<T> : INamedFactory<T>
{
private readonly Func<string, T> factory;
public NamedDelegateFactory(Func<string, T> factory)
{
this.factory = factory;
}
public T GetByKey(string key)
{
return this.factory(key);
}
object INamedFactory.GetByKey(string key)
{
return this.factory(key);
}
}
可在容器中註冊如下:
var adapter = new LightCoreServiceLocatorAdapter(builder.Build());
Microsoft.Practices.ServiceLocation.ServiceLocator
.SetLocatorProvider(() => adapter);
您可以使用註冊的所有命名實例:
var factory = new NamedDelegateFactory<IMyType>(key =>
{
if (key == "Cool") return new MyType1();
else return new MyType2();
});
var builder = new ContainerBuilder();
builder.Register<INamedFactory<IMyType>>(c => factory);
接下來,LightCoreServiceLocatorAdapter
可以如下創建INamedFactory<T>
接口並使用NamedDelegateFactory<T>
包裝在一個委託或實現一個自定義類型,實現INamedFactory<T>
。
服務定位器模式[由定義不完整](http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx)。如果可以,請轉到依賴注入模式。 – Steven
悲傷但真實,我知道Mark Seemann的博客文章。不幸的是,我不能移動,因爲它是使用ServiceLocator的傳統應用程序。 –
你總是可以,但這需要時間。這一天不會發生,這是肯定的。 – Steven