C#,Autofac:在寄存器<>中未提供NamedParameter. [英] C#, Autofac: NamedParameter is not provided in Register<>

查看:81
本文介绍了C#,Autofac:在寄存器<>中未提供NamedParameter.的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此刻我正在尝试一些autofac功能,并且在NamedParameter方面苦苦挣扎.

I'm trying some autofac features at the moment and are struggling with the NamedParameter.

我创建了一个非常简单的示例,其中IFooHappyFooSadFoo实现. IFooUser在构造函数中需要一个IFoo对象,并使用该对象将某些内容打印到控制台.

I created a very simple example, where IFoo is realized by HappyFoo and SadFoo. IFooUser expects an IFoo object in the constructor and uses it to print something to the console.

以下代码显示了我如何构建IFooUser对象,该对象将基于得分"值使用IFoo对象.

The code below shows how I'm trying to build a IFooUser object which shall use an IFoo object based on a 'score' value.

        var builder = new ContainerBuilder();

        builder.RegisterType<NormalFooUser>().As<IFooUser>();

        builder.Register<IFoo>((context, parameters) =>
        {
            var score = parameters.Named<int>("score"); // ! Exception !
            if (score >= 100)
            {
                return new HappyFoo();
            } 
            return new SadFoo();
        });

        var container = builder.Build();

        using (var scope = container.BeginLifetimeScope())
        {
            scope.Resolve<IFooUser>(new NamedParameter("score", 90)).useFoo();
        }

不幸的是,当我执行此代码时,parameters序列不包含任何值=>异常!当我决定IFoo一切正常时:

Unfortunately when I execute this code, the parameters sequence doesn't hold any values => Exception! When I resolve to IFooeverything works fine:

       scope.Resolve<IFoo>(new NamedParameter("score", 90)).foo(); // Works

但这不是我想要做的.因此,我想知道如何使用与NamedParameter的得分"相对应的IFoo对象构造IFooUser.

But this is not what I want to do. So I'm wondering how I can construct a IFooUser with an IFoo object corresponding to the 'score' with the NamedParameter.

完整的代码示例可以找到此处为要点

The complete code-sample can be found here as gist

谢谢.

推荐答案

NamedParameter旨在配置请求的组件,而不是整个依赖关系图,该参数不会在整个注册过程中传播,因此它不是 context 参数.

NamedParameter is intended to configure the requested component and not the whole dependency graph, the parameter is not propagated through the whole registration process it is not a context parameter.

如果要具有 context ,则可以实现这样的组件,该组件将存储一些属性.

If you want to have a context you can implement such a component which will store some properties.

// interface 
interface IContext {
    T Get<T>(String name); 
    void Set<T>(String name, T value); 
}

// registration 
builder.RegisterType<FooContext>().As<IContext>();
builder.Register<IFoo>(c =>
{
    var score = c.Resolve<IContext>().Get<Int32>("score"); 
    if (score >= 100)
    {
        return new HappyFoo();
    }
    return new SadFoo();
});


// usage 
using (ILifetimeScope scope = container.BeginLifetimeScope())
{
    scope.Resolve<IContext>().Set("score", 90); 
    scope.Resolve<IFooUser>().useFoo();
}

此方法的优点是,您可以在当前生命周期范围内随时设置上下文属性.您也可以想象没有Set方法的实现,该方法将根据您想要的内容检索值.

The advantage of this approach is that you can set the context property whenever you want in your current lifetime scope. You can also imagine implementation without Set method which will retrieve value based on whatever you want.

做同一件事的另一种方法是使用Func<Int32, IFoo>依赖项和TypedAs方法

Another way of doing the same thing is by using a Func<Int32, IFoo> dependency and the TypedAs methods

builder.Register<IFoo>((c, p) =>
{
    Int32 score = p.TypedAs<Int32>(); 
    if (score >= 100)
    {
        return new HappyFoo();
    }
    return new SadFoo();
});

当然,您必须更改IFooUser界面和实现

and of course you have to change the IFooUser interface and implementation

public class NormalFooUser : IFooUser
{
    private readonly Func<Int32, IFoo> _fooBuilder;

    public NormalFooUser(Func<Int32,IFoo> fooBuilder)
    {
        _fooBuilder = fooBuilder;
    }

    public void useFoo(Int32 score)
    {
        _fooBuilder(score).foo();
    }
}

这篇关于C#,Autofac:在寄存器&lt;&gt;中未提供NamedParameter.的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆