C#,Autofac:在寄存器<>中未提供NamedParameter. [英] C#, Autofac: NamedParameter is not provided in Register<>
问题描述
此刻我正在尝试一些autofac功能,并且在NamedParameter方面苦苦挣扎.
I'm trying some autofac features at the moment and are struggling with the NamedParameter.
我创建了一个非常简单的示例,其中IFoo
由HappyFoo
和SadFoo
实现. 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 IFoo
everything 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:在寄存器<>中未提供NamedParameter.的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!