C# Autofac参数传递和自动接线

C# Autofac参数传递和自动接线,c#,dependency-injection,autofac,C#,Dependency Injection,Autofac,无法了解传入Autofac的参数,以下代码不起作用: class Config { public Config(IDictionary<string, string> conf) {} } class Consumer { public Consumer(Config config) {} } void Main() { var builder = new Autofac.Builder.ContainerBuilder(); builder.Re

无法了解传入Autofac的参数,以下代码不起作用:

class Config {
    public Config(IDictionary<string, string> conf) {}
}

class Consumer {
    public Consumer(Config config) {}
}

void Main()
{
    var builder = new Autofac.Builder.ContainerBuilder();
    builder.Register<Config>();
    builder.Register<Consumer>();
    using(var container = builder.Build()){
        IDictionary<string,string> parameters = new Dictionary<string,string>();
        var consumer = container.Resolve<Consumer>(Autofac.TypedParameter.From(parameters));
    }
}
但以下代码确实有效:

IDictionary参数=新字典();
var config=container.Resolve(Autofac.TypedParameter.From(parameters));
var consumer=container.Resolve(Autofac.TypedParameter.From(config));

Autofac显然是在假设字典本身是可解析类型的情况下尝试解析Config类的参数。我不知道autofac的语法如何做到这一点。但是在注册配置类型时,您可能需要执行更多步骤,例如。G给它一个新字典中传递的委托。

在此重复Autofac邮件列表中的答案:

传递给Resolve的参数仅与的直接实现者相关 您正在解析的服务,因此将配置的参数传递给解析 呼叫消费者将不起作用。 解决方法是将您的消费者注册更改为:

builder.Register((c, p) => new Consumer(c.Resolve<Config>(p))); 
builder.Register((c,p)=>newconsumer(c.Resolve(p));

不幸的是,像Autofac这样的IoC容器没有配备“请阅读我的大脑模块”

你想做的基本上是说“我知道这里涉及的一种类型需要一本字典,我需要一个类型为Consumer的服务,你能试着弄清楚我在做什么,然后做正确的事情吗?”


如果解析一个服务并指定一个参数,则该参数将尝试用于该特定服务。容器不会尝试将该参数值传播到任何依赖项。

您的问题不是很清楚。为了我们这些不是autofac用户的人,您能展示p、config、TypedParameter.From和container.Resolve的声明吗?另外,请指定它以什么方式“不工作”-编译时错误?异常?通过LINQPad(reference Autofac.dll)中的可运行示例进行了说明,您是对的!但接下来的问题出现了,若我改为按如下方式注册配置:builder.register((c,p)=>newconfig(p.TypedAs());p在解析时间为空!嗯,可能是因为你给了autofac一个委托,但是委托在运行时仍然没有字典。尝试在您的代理中实际提供一个新字典,类似这样(请注意,我仍然不知道autofac的确切计算):builder.Register((c)=>new Config(new Dictionary());这不总是给Config一个空字典吗?不管在解析时传递了哪些参数?是的,它会。在您的示例代码中,您在解析时也会这样做,将一个新字典放入Config.haha,true;)但关键是能够注入自定义参数。。字典的内容只有在运行时才能知道。我猜您的意思是:builder.Register((c,p)=>newconsumer(c.Resolve(p));因为这很有效!谢谢你,尼古拉斯!“终于有人知道autofac了”你指的是作者,是的,当然:)当然,我的第一次尝试很幼稚,但没有出路,如果参数被当作注册来处理,它就可以工作了?可能是的,autofac应该能够弄清楚,但你需要将参数作为服务预先注册到autofac。就我个人而言,我不推荐使用构造函数参数的服务,它总是一个泄漏的服务,因为它将实现细节泄漏到使用它的代码中,使得以后很难替换该服务。把一个配置文件名传递给它,然后如果你决定使用一个从数据库读取配置的服务,那么,我知道,我的解决方案不是点亮的,但问题是,我希望用户能够配置要使用的服务类型。但该服务也需要不同的配置,所以现在这些服务配置作为IDictionary传入。。我希望有更好的解决方案,但这个工厂是我迄今为止最好的尝试。你不能简单地将配置提供程序创建为服务,接口中包含返回字典的方法吗?通过这种方式,您可以轻松地对代码进行单元测试(提供代码驱动的配置)并连接代码,而无需在调用站点指定任何配置。@LasseV.Karlsen,我认为构造函数是实现细节,因此不会导致代码泄漏。(见附件)。如果不在合成根目录中,您希望将所需配置放在何处?
IDictionary<string,string> parameters = new Dictionary<string,string>();
var config = container.Resolve<Config>(Autofac.TypedParameter.From(parameters));
var consumer = container.Resolve<Consumer>(Autofac.TypedParameter.From(config));
builder.Register((c, p) => new Consumer(c.Resolve<Config>(p)));