KeyFilter可以通过多个级别工作吗?

问题描述 投票:1回答:1

我有一个数据访问类,其配置数据作为依赖项。然后,我有一个“数据使用者”类,它具有数据访问类作为其依赖项。我希望能够在使用者的构造函数中选择配置类。

我使用KeyFilter属性进行单元测试。但是,它只能通过一个层工作 - 我必须消除中间数据访问类层。这对我的实际用例不起作用,但我相信它显示我正确使用了KeyFilter。

这是一个通过的测试:

    [TestMethod]
    public void ChooseCorrectlyThroughInterface()
    {
        var wrapper = new AutofacWrapper();

        wrapper.Register<ITest, Test1>();
        wrapper.Register<ITest, Test2>(UseTest2);
        wrapper.Register<IConsumer1, Consumer1>();
        wrapper.Register<IConsumer2, Consumer2>();

        using (wrapper.BeginScope())
        {
            var c1 = wrapper.Get<IConsumer1>();
            Assert.AreEqual("Test1", c1.ToString());

            var c2 = wrapper.Get<IConsumer2>();
            Assert.AreEqual("Test2", c2.ToString());
        }
    }

Consumer1的构造函数如下所示:

    public Consumer1(ITest test)

但Consumer2使用KeyFilter:

    public Consumer2([KeyFilter(NamedBindingsShould.UseTest2)] ITest test)

我的wrapper.Register方法如下所示:

    if (string.IsNullOrEmpty(name))
    {
        Builder.RegisterType<TImplementation>()
            .As<TInterface>()
            .WithAttributeFiltering();
    }
    else
    {
        Builder.RegisterType<TImplementation>()
            .Named<TInterface>(name)
            .WithAttributeFiltering();
    }

一切正常,测试通过。但是,真正的用例是在构造函数上定义KeyFilter的位置和需要更改的依赖项之间添加一个层。

我想指定两个不同的数据库配置类:

    wrapper.Register<IDatabaseConfigTest, DatabaseConfigDefault>();
    wrapper.Register<IDatabaseConfigTest, DatabaseConfigAlternate>(Alternate);

但只有一个数据访问类:

    wrapper.Register<IDatabaseTest, DatabaseTest>();

使用此构造函数:

    public DatabaseTest(IDatabaseConfigTest config)

并在数据使用者类构造函数中指定KeyFilter:

    public DataConsumerDefault(IDatabaseTest database)

    public DataConsumerAlternate([KeyFilter(NamedBindingsShould.Alternate)] IDatabaseTest database)

我在Ninject工作了很多功夫(没有双关语),但是我试图改用Autofac,我似乎无法让它工作。

Autofac有可能吗?除了KeyFilter,我还能使用不同的方法吗?我有一个示例测试项目,如果需要我可以附加或发送。我还可以提供有关如何在Ninject中执行此操作的详细信息。

autofac
1个回答
1
投票

Soooo ...感谢https://autofaccn.readthedocs.io/en/latest/faq/select-by-context.html?highlight=AttributedMetadataModule%20#option-3-use-keyed-services

我将wrapper.Register方法更改为:

        if (string.IsNullOrEmpty(name))
        {
            Builder.RegisterType<TImplementation>()
                .As<TInterface>()
                .WithAttributeFiltering();
        }
        else
        {
            Builder.RegisterType<TImplementation>()
                .Named<TInterface>(name)
                .WithParameter(
                    new ResolvedParameter(
                        (pi, ctx) => ctx.IsRegisteredWithName(name, pi.ParameterType),
                        (pi, ctx) => ctx.ResolveNamed(name, pi.ParameterType)))
                .WithAttributeFiltering();
        }

它工作了!

谢谢你的文档。

© www.soinside.com 2019 - 2024. All rights reserved.