我正在使用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()
}


这使我步入正轨,但是我感觉可以做得更好-这就是为什么我现在向专家求助。

提前致谢。

最佳答案

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,并且只会创建一个IServiceA

如果这还不够,您可以使用InstancePerMatchingLifetimeScope进行操作,但这会使您的代码和注册非常难以阅读和调试。 InstancePerLifetimeScope应该足够了。

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

builder.Register(ctx =>
{
    IServiceA serviceA = ctx.Resolve<IServiceA>();
    IServiceB serviceB = ctx.Resolve<IServiceB>(TypedParameter.From(serviceA));
    IServiceC serviceC = ctx.Resolve<IServiceC>(TypedParameter.From(serviceA));
    IServiceD serviceD = ctx.Resolve<IServiceD>(TypedParameter.From(serviceA), TypedParameter.From(serviceB), TypedParameter.From(serviceC));
    return serviceD;
}).As<IServiceD>();


但是不是很优雅。

07-28 02:37