簡體   English   中英

Autofac忽略了注冊沖突

[英]Autofac ignores registration conflicts

我有以下測試

[TestFixture]
public class Test
{
    public interface IMy { }

    class MyClass : IMy { }

    class MyClass2 : IMy { }

    [Test]
    public static void Go()
    {
        var builder = new ContainerBuilder();
        builder.RegisterType<MyClass>().AsImplementedInterfaces();
        builder.RegisterType<MyClass2>().AsImplementedInterfaces();
        var container = builder.Build();
        var resolved = container.Resolve<IMy>();
        Console.WriteLine(resolved);
    }
}

為什么當實現明顯沖突時它不會拋出異常? 如果發現這樣的沖突,如何使它拋出異常?

注冊檢查的UPDATE解決方案幾乎沒問題,但是失敗的情況很簡單:

[TestFixture]
public class Test
{
    public interface IPlugin
    {
    }

    public interface IMy
    {

    }

    class MyClass : IMy, IPlugin
    {
        public void Dispose()
        {
        }
    }

    class MyClass2 : IPlugin
    {
        public void Dispose()
        {
        }
    }

    public class SingleRegistrationModule : Module
    {
        protected override void AttachToComponentRegistration(
            IComponentRegistry componentRegistry, 
            IComponentRegistration registration)
        {
            foreach (var service in registration.Services)
            {
                var registrations = componentRegistry.RegistrationsFor(service);
                if (registrations.Count() > 1)
                {
                    throw new Exception(
                        "Can't register '{registration.Activator.LimitType}' as '{service}'" + 
                        " because '{registrations.First().Activator.LimitType}' is already registered");
                }
            }
        }
    }

    [Test]
    public static void Go()
    {
        var builder = new ContainerBuilder();
        builder.RegisterType<MyClass>().AsImplementedInterfaces();
        builder.RegisterType<MyClass2>().AsImplementedInterfaces();
        builder.RegisterModule<SingleRegistrationModule>();
        var container = builder.Build();
        var resolved = container.Resolve<IMy>();
        Console.WriteLine(resolved);
    }
}

在這種情況下,沒有人解析IInitializable,因此可以接受多個實現。 此外,有些情況下mulltiple實現正常,例如IPluginToSomething

Autofac不會拋出異常的原因是因為Autofac認為同一接口的多個注冊是集合的一部分。 例:

builder.RegisterType<MyClass>().As<IMy>();
builder.RegisterType<MyClass2>().As<IMy>();
var container = builder.Build();
var collection = container.Resolve<IEnumerable<IMy>>();
Console.WriteLine(collection.Count()); // prints "2"

如果進行多次注冊,調用Resolve<IMy>()將只解析其中一個(第一個或最后一個,但我總是忘記它是哪一個)。 我個人認為這是Autofac(以及其他DI容器)中的設計缺陷,因為這會導致應用程序無聲地失敗,而不是快速失敗。 簡單的噴油器的選擇,已作出嚴格區分藏品的登記(如解釋在這里 ),以防止這些類型的配置錯誤。

正如Steven所說, Autofac將考慮將同一服務的多個注冊作為集合的一部分。

如果您不想要此行為,可以使用Autofac模塊添加檢查:

public class SingleRegistrationModule : Module
{
    protected override void AttachToComponentRegistration(
        IComponentRegistry componentRegistry, 
        IComponentRegistration registration)
    {
        foreach (var service in registration.Services)
        {
            var registrations = componentRegistry.RegistrationsFor(service);
            if (registrations.Count() > 1)
            {
                throw new Exception(
                    $"Can't register '{registration.Activator.LimitType}' as '{service}'" + 
                    $" because '{registrations.First().Activator.LimitType}' is already registered");
            }
        }
    }
}

然后您可以使用以下方式注冊模塊:

builder.RegisterModule<SingleRegistrationModule>();

構建容器時將拋出異常。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM