Autofac使用不同的参数解析同一类实例



我有一个Xamarin.Forms应用程序,我正在使用Autofac进行DI。

所以我想要的很简单,但我无法做一些看起来像是犯罪的事情。

因此,我有一个类,它有两个构造函数,这两个构造函数都有一个参数,并且基于某些条件,我想解析其中一个。举个例子,我有一个类a,我想要的是基于条件B或C应该被解决。

例如:

public class A
{
public A(B bObject)
{...}
public A(C cObject)
{...}
}

但我不知道该怎么做。我试着做了如下的事情:

注册:

builder.RegisterType<A>().
UsingConstructor(typeof(C)).
Named<A>(nameof(C));
builder.RegisterType<A>().
UsingConstructor(typeof(B)).
Named<A>(nameof(B));

解析:

DiContainer.ResolveNamed<A>(nameof(B));
DiContainer.ResolveNamed<A>(nameof(C));

注:我已经在集装箱中注册了B和C,如下所示:

builder.RegisterType<B>();
builder.RegisterType<C>()

我对AutoFac有点陌生,我甚至不确定这是否是正确的方式,我认为这与我注册了两次有关,我不确定。

非常感谢任何建议或帮助。

您可以尝试为此使用Autofac lambda注册,并使用以下代码段(此处的c参数为IComponentContext实例(执行注册

var builder = new ContainerBuilder();
builder.Register(
(c, p) =>
{
var condition = p.Named<bool>("condition");
return condition ? new A(c.Resolve<B>()) : new A(c.Resolve<C>());
});
builder.RegisterType<B>();
builder.RegisterType<C>();

然后通过将参数传递给lambda表达式来解析A。您可以使用TypedParameter而不是命名的(仅限常数值(或ResolvedParameter(动态值(

var a = container.Resolve<A>(new NamedParameter("condition", true));

如果您不想显式调用Resolve,可以查看委托工厂(例如Func<T>(

这里有一个简单的解决方法:

你可以将类B和C包装成另一个类,然后在autofac:中注册

public class Wrapper {
public B BObject;
public C CObject;
}

然后你可以这样做一点(我不知道解决它的正确方法,因为我目前没有IDE,但我希望你能理解我在这里做什么(:

DiContainer.ResolveNamed<A>(new Wrapper(){BObject = Binstance});

另一种解决方案:

您还可以根据需要注册B或C。

如果您希望用B实例化该类,请在autofac上注册B,然后解析该类。

但是这个类需要有两个构造函数。一个用B作为参数,一个用C。。。

我认为Autofac会根据注册的内容解决问题。

我相信你已经非常接近了,你确实需要将Parameter定义传递给你的Resolve

public class B { }
public class C { }
public class A
{
public A(B bObject){ Console.WriteLine("I am constructor A typeof(B)");}
public A(C cObject){ Console.WriteLine("I am constructor A typeof(C)");}    
}
void Main()
{
var builder = new ContainerBuilder();
builder.RegisterType<A>().UsingConstructor(typeof(B)).Named<A>(nameof(B));
builder.RegisterType<A>().UsingConstructor(typeof(C)).Named<A>(nameof(C));
//it doesn't really matter if these are registered as you're using nameof() to identify the objects - that's essentially string
builder.RegisterType<B>();
builder.RegisterType<C>();
var container = builder.Build();
var a1 = container.ResolveNamed<A>(nameof(B), new TypedParameter(typeof(B), new B()));
var a2 = container.ResolveNamed<A>(nameof(C), new TypedParameter(typeof(C), new C()));  
}

最新更新