使用“构造函数范围”注入依赖项 - autofac

时间:2015-06-20 06:32:21

标签: c# autofac

我正在使用autofac 3.5.x,我有类似的设置:

public class ServiceA : IServiceA { }
public class ServiceB : IServiceB { public ServiceB(IServiceA sa) { } }
public class ServiceC : IServiceC { public ServiceC(IServiceA sa) { } }
public class ServiceD : IServiceD { public ServiceD(IServiceA sa, IServiceB sb, IServiceC sc) {} }

在我的容器中,我有以下注册:

builder.RegisterType<ServiceA>.As<IServiceA>();
builder.RegisterType<ServiceB>.As<IServiceB>();
builder.RegisterType<ServiceC>.As<IServiceC>();
builder.RegisterType<ServiceD>.As<IServiceD>();

这就是我想要的:当我从容器中请求新的IServiceD时,我希望将相同的IServiceA实例注入IServiceD及其依赖项IServiceBIServiceC。我不是在寻找全局单例范围。下次我要求IServiceD实例时,必须创建一个新的IServiceA实例(我知道你不能创建一个接口实例,但我认为你得到了要点)。

说明;当我向autofac容器询问IServiceD时,我希望发生以下情况:

public class ServiceD : IServiceD
{
    public ServiceD(IServiceA sa, IServiceB sb, IServiceC sc)
    {
        // SA should be the same (but it is not)
        sa.GetHashCode() == sb.GetServiceA().GetHashCode() == sc.GetServiceA().GetHashCode()
    }
}

请注意,GetServiceA()方法仅用于说明我的观点。

所以是的,我想我正在寻找一种方法来告诉autofac,当它解析IServiceD时,它应该创建一个ServiceA的单身,但仅限于ServiceD的范围构造

现在,我对代表工厂使用autofacs支持,并要求:

public ServiceD(IServiceA sa, Func<IServiceA, IServiceB> fb, Func<IServiceA, IServiceC> fc) : IServiceD
{
     var sb = fb(sa); // Manually inject the same instance of ServiceA
     var sc = fc(sa); // Manually inject the same instance of ServiceA

     // ServiceA is now the same instance
     sa.GetHashCode() == sb.GetServiceA().GetHashCode() == sc.GetServiceA().GetHashCode()
}

这让我开始了,但我觉得可以做得更好 - 这就是为什么我现在转向专家。

提前致谢。

1 个答案:

答案 0 :(得分:2)

FileField可能适合您的需要。它允许您在每个生命周期范围内拥有一个实例。

InstancePerLifetimeScope

然后,每次您在新范围内解决builder.RegisterType<ServiceA>().As<IServiceA>().InstancePerLifetimeScope(); builder.RegisterType<ServiceB>().As<IServiceB>().InstancePerLifetimeScope(); builder.RegisterType<ServiceC>().As<IServiceC>().InstancePerLifetimeScope(); builder.RegisterType<ServiceD>().As<IServiceD>().InstancePerLifetimeScope(); 时,您将只有IServiceD的单个实例

IServiceA

如果您无法创建新using (ILifetimeScope scope = container.BeginLifetimeScope()) { // only an instance of IServiceA will be created for this scope scope.Resolve<IServiceD>(); } ,则可以使用ILifetimeScope类型,这是一个轻量级的生命周期镜。

Owned<T>

每次解析using (Owned<IServiceD> ownedD = container.Resolve<Owned<IServiceD>>()) { IServiceD serviceD = ownedD.Value; } 时,系统都会创建一个新的Owned<IserviceD>,并且只会创建一个ILifetimeScope

如果还不够,您可以使用InstancePerMatchingLifetimeScope,但这会使您的代码和注册很难阅读和调试。 IServiceA应该足够了。

另一种解决方案是使用这种注册。

InstancePerLifetimeScope

但不是很优雅。