Autofac разрешает компоненты со смешанной областью действия - PullRequest
4 голосов
/ 25 октября 2011

Я использую Autofac 2.5 в asp.net, и у меня возникла проблема, из-за которой компоненты области действия времени жизни решаются как зависимости компонентов одного экземпляра, тем самым разрушая мою безопасность потоков.Это проблема с регистрациями, но я подумал, что 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 - это может быть потенциально опасно в веб-среде.Убедиться в том, что все ваши разработчики получили правильные регистрации, может быть очень сложно.Вот небольшой метод расширения для 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();

1 Ответ

3 голосов
/ 25 октября 2011

Да - необходимо указать дочернюю область и явно связать с ней компонент A. В противном случае, как вы заметили, экземпляр A создается в корневой области (контейнере).

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

И ...

// Replace scope creation with:
using (var lifetime = container.BeginLifetimeScope("child")) {
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...