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

时间:2019-11-11 12:46:25

标签: c# xamarin dependency-injection 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有点陌生,我甚至不确定这是否是正确的方法,我认为这与我不确定两次注册有关。

任何建议或帮助都将受到赞赏。

3 个答案:

答案 0 :(得分:0)

这是一个简单的解决方法:

您可以将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将会解决,具体取决于注册的内容。

答案 1 :(得分:0)

您可以尝试使用lambda registration来实现。使用以下代码段(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>();

然后通过passing解析lambda表达式的参数来A。您可以使用TypedParameter代替命名(仅恒定值)或ResolvedParameter(动态值)

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

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

答案 2 :(得分:0)

我相信您非常亲密,您实际上需要将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()));  
}