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

时间:2019-02-20 01:20:11

标签: autofac

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

我使用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中完成操作的详细信息。

1 个答案:

答案 0 :(得分: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();
        }

成功了!

谢谢您的文档。