将IOC容器注册到自己

时间:2016-05-18 12:31:54

标签: c# dependency-injection inversion-of-control simple-injector constructor-injection

我们说我有一个接口IDependencyResolver:

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的构造函数是否正确?

1 个答案:

答案 0 :(得分:2)

  

如果我需要在使用服务定位器模式的构造函数中注入IDependencyResolver,我该怎么办? (是的,我知道......反模式......但除此之外)

这不应该被搁置。尽管你在UnitOfWork中对你的容器进行回调的方法很好,但这种IDependencyResolver抽象的(ab)使用可以通过代码库快速传播到地方绝对不好的地方。

IDependencyResolver抽象的使用应限于组合根。但是由于组合根已经知道你正在使用的确切DI库的存在,所以IDependencyResolver抽象没有直接依赖于Container本身的好处。

因此,您的IUnitOfWork实现应该在内部的Compostion Root中定义,并且应该如下所示:

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();