gpt4 book ai didi

.net - Autofac 解析具有混合范围的组件

转载 作者:行者123 更新时间:2023-12-01 19:27:14 31 4
gpt4 key购买 nike

我在 asp.net 中使用 Autofac 2.5,但遇到一个问题:生命周期范围组件被解析为单实例组件的依赖项,从而破坏了我的线程安全。这是注册问题,但我认为 Autofac 将此视为违规并会抛出异常。

    private class A{}

private class B
{
public B(A a){}
}

[Test]
[ExpectedException()]
public void SingleInstanceCannotResolveLifetimeDependency()
{
var builder = new ContainerBuilder();
builder.RegisterType<A>()
.InstancePerLifetimeScope();
builder.RegisterType<B>()
.SingleInstance();

using (var container = builder.Build())
{
using (var lifetime = container.BeginLifetimeScope())
{
//should throw an exception
//because B is scoped singleton but A is only scoped for the lifetime
var b = lifetime.Resolve<B>();
}
}
}

如果发生这种情况,有没有办法让 Autofac 抛出依赖解析异常?

更新尽管这是 Autofac 的正确行为(SingleInstance 只是 Root 生命周期范围),但它在 Web 环境中可能存在潜在危险。确保所有开发人员获得正确的注册可能是一件痛苦的事情。这是 Autofac 的一个小扩展方法,用于检查实例查找以确保生命周期范围内的实例不会在根范围中得到解析。我知道它帮助我们解决了网络项目中的生命周期问题。

    public static class NoLifetimeResolutionAtRootScopeExtensions
{
/// <summary>
/// Prevents instances that are lifetime registration from being resolved in the root scope
/// </summary>
public static void NoLifetimeResolutionAtRootScope(this IContainer container)
{
LifetimeScopeBeginning(null, new LifetimeScopeBeginningEventArgs(container));
}

private static void LifetimeScopeBeginning(object sender, LifetimeScopeBeginningEventArgs e)
{
e.LifetimeScope.ResolveOperationBeginning += ResolveOperationBeginning;
e.LifetimeScope.ChildLifetimeScopeBeginning += LifetimeScopeBeginning;
}

private static void ResolveOperationBeginning(object sender, ResolveOperationBeginningEventArgs e)
{
e.ResolveOperation.InstanceLookupBeginning += InstanceLookupBeginning;
}

private static void InstanceLookupBeginning(object sender, InstanceLookupBeginningEventArgs e)
{
var registration = e.InstanceLookup.ComponentRegistration;
var activationScope = e.InstanceLookup.ActivationScope;

if (registration.Ownership != InstanceOwnership.ExternallyOwned
&& registration.Sharing == InstanceSharing.Shared
&& !(registration.Lifetime is RootScopeLifetime)
&& activationScope.Tag.Equals("root"))
{
//would be really nice to be able to get a resolution stack here
throw new DependencyResolutionException(string.Format(
"Cannot resolve a lifetime instance of {0} at the root scope.", registration.Target))
}
}
}

只需在创建容器时应用此方法,当在根范围内解析生命周期范围的服务时,您就会抛出异常。

container.NoLifetimeResolutionAtRootScope();

最佳答案

是的 - 您需要命名子作用域,并将组件 A 与其显式关联。否则,正如您所观察到的,A 实例将在根(容器)范围内创建。

// Replace `A` registration with:
builder.RegisterType<A>().InstancePerMatchingLifetimeScope("child");

还有...

// Replace scope creation with:
using (var lifetime = container.BeginLifetimeScope("child")) {

关于.net - Autofac 解析具有混合范围的组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7882532/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com