2

比方說,我有一個接口的IDependencyResolver:註冊IOC容器自

public interface IDependencyResolver{ 
    T Resolve<T>() where T: class; 
    object Resolve(Type source); 
} 

以及採用SimpleInjector的實現:

public class SIDependencyResolver:IDependencyResolver{ 
    private readonly Container _container; 
    public SIDependencyResolver(Container container){ 
     _container = container; 
     _container.Options.DefaultScopedLifestyle = new WcfOperationLifeStyle(); 
     RegisterDependencies(_container, LifeStyle.Scoped); 
    } 
    public T Resolve<T>() where T:class{ 
     return _container.GetInstance<T>(); 
    } 
    public object Resolve(Type source){ 
     return _container.GetInstance(source); 
    } 
    public void RegisterDependencies(Container container, LifeStyle lifeStyle){ 
     //register dependencies + register self 
    } 
} 

我需要什麼,如果我需要的IDependencyResolver做注入一個使用服務定位器模式的構造函數? (是的,我知道...反模式...但是這一邊)

public class UnitOfWork: IUnitOfWork{ 
    private readonly IDependencyResolver _resolver; 
    public UnitOfWork(IDependencyResolver resolver){ 
     _resolver = resolver; 
    } 
    public IReadRepository<T> Read<T>(){ 
     return _resolver.Resolve<IReadRepository<T>>(); 
    } 
    public IWriteRepository<T> Write<T>(){ 
     return _resolve.Resolve<IWriteRepository<T>>(); 
    } 
} 

在過去,我總是註冊的依賴解析器自己作爲一個單身,所以不與範圍的生活方式,因爲這給了我問題。

container.Register<IDependencyResolver, SIDependencyResolver>(LifeStyle.Singleton); 

首先,這是正確的方式(例如,在WCF範圍的情況下,與單身的生活方式),要做到這一點,還是有另一種方式來做到這一點?
其次,將SimpleInjector.Container傳遞給我的dependencyResolver的構造函數是否正確?

回答

2

如果我需要在使用服務定位器模式的構造函數中注入IDependencyResolver,我需要做什麼? (是的,我知道...反模式...但這一邊)

這不應該放在一邊。雖然你的回調方法如你在UnitOfWork中做的那樣容易,但(ab)使用這樣的IDependencyResolver抽象可以通過代碼快速傳播到絕對不好的地方。

IDependencyResolver抽象的用法應限制在組合根。但是由於組合根已經知道您正在使用的確切DI庫的存在,因此具有這種抽象並不直接依賴於Container本身。

所以你IUnitOfWork實現應內您Compostion根被定義並應如下所示:

private sealed class SimpleInjectorUnitOfWork : IUnitOfWork { 
    private readonly Container _container; 
    public UnitOfWork(Container container){ 
     _container = container; 
    } 
    public IReadRepository<T> Read<T>() => _container.GetInstance<IReadRepository<T>>(); 
    public IWriteRepository<T> Write<T>() => _container.GetInstance<IWriteRepository<T>>(); 
} 

註冊可以做如下:

container.RegisterSingleton<IUnitOfWork>(new SimpleInjectorUnitOfWork(container)); 

在過去的我總是註冊依賴解析器自我作爲一個單身,所以沒有範圍的生活方式,因爲這給了我的問題。

我不清楚你有什麼問題,但有一件事情會引起麻煩的是在構造函數中設置DefaultScopedLifestyle,而類型是由容器自動連接的。將這個調用從這樣的構造函數中移出要好得多;它使得它更清晰:

var container = new Container(); 
container.Options.DefaultScopedLifestyle = new WcfOperationLifeStyle(); 
+0

創建此抽象的好處(在我看來)是,我不需要將SimpleInjector包添加到添加UnitOfWork的數據層。如果我選擇將IOC容器更改爲Unity/Ninject/AutoFac/...,則只需創建IDependencyResolver的新實現。 – RubenHerman

+0

所以你建議將我的UnitOfWork從我的數據層項目移動到依賴項解析項目,該項目也包含我對simpleinjector包的引用? – RubenHerman

+0

我建議你將'IUnitOfWork'抽象完全留在原來的位置,並在配置容器的應用程序的啓動路徑中定義'SimpleInjectorUnitOfWork'適配器(這個地方通常稱爲「組合根」)。 – Steven