使用 "constructor scope" 注入依赖 - autofac
Inject dependency with "constructor scope" - 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
及其依赖项 IServiceB
和 IServiceC
。不过,我并不是在寻找全局单例范围。下次我请求 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>();
但不是很优雅。
我正在使用 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
及其依赖项 IServiceB
和 IServiceC
。不过,我并不是在寻找全局单例范围。下次我请求 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>();
但不是很优雅。