Autofac 用不同的参数解析同一个 class 实例
Autofac resolve the same class instance with different parameters
我有一个 Xamarin.Forms
应用程序,我在其中使用 Autofac 进行 DI。
所以我想要的很简单,但我无法做一些看起来很困难的事情。
所以我有一个 class,它有两个构造函数,它们都有一个参数,并且基于某些条件我想解析其中一个。例如,我有一个 class 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 有点陌生,我什至不确定这是否正确,我认为这与我注册两次有关,我不确定。
非常感谢任何建议或帮助。
这是一个简单的解决方法:
您可以将 class B 和 C 包装到另一个 class 中,然后在 autofac 中注册:
public class Wrapper {
public B BObject;
public C CObject;
}
然后你可以像这样做一点(我不知道解决它的正确方法,因为我目前没有 IDE,但我希望你明白我在这里做什么):
DiContainer.ResolveNamed<A>(new Wrapper(){BObject = Binstance});
另一个解决方案:
您还可以根据需要注册 B 或 C。
如果您希望 class 将用 B 实例化,请在 autofac 上注册 B,然后解析 class。
但是class需要有两个构造函数。一个以 B 作为参数,一个以 C ...
我认为 Autofac 会根据注册的内容解决。
您可以尝试为此使用 Autofac 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 一个参数解析 A
到 lambda 表达式。您可以使用 TypedParameter
而不是命名(仅限常量值)或 ResolvedParameter
(动态值)
var a = container.Resolve<A>(new NamedParameter("condition", true));
如果您不想显式调用 Resolve
,您可以查看委托 factories(例如 Func<T>
)
我相信你非常接近,你确实需要将 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()));
}
我有一个 Xamarin.Forms
应用程序,我在其中使用 Autofac 进行 DI。
所以我想要的很简单,但我无法做一些看起来很困难的事情。
所以我有一个 class,它有两个构造函数,它们都有一个参数,并且基于某些条件我想解析其中一个。例如,我有一个 class 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 有点陌生,我什至不确定这是否正确,我认为这与我注册两次有关,我不确定。
非常感谢任何建议或帮助。
这是一个简单的解决方法:
您可以将 class B 和 C 包装到另一个 class 中,然后在 autofac 中注册:
public class Wrapper {
public B BObject;
public C CObject;
}
然后你可以像这样做一点(我不知道解决它的正确方法,因为我目前没有 IDE,但我希望你明白我在这里做什么):
DiContainer.ResolveNamed<A>(new Wrapper(){BObject = Binstance});
另一个解决方案:
您还可以根据需要注册 B 或 C。
如果您希望 class 将用 B 实例化,请在 autofac 上注册 B,然后解析 class。
但是class需要有两个构造函数。一个以 B 作为参数,一个以 C ...
我认为 Autofac 会根据注册的内容解决。
您可以尝试为此使用 Autofac 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 一个参数解析 A
到 lambda 表达式。您可以使用 TypedParameter
而不是命名(仅限常量值)或 ResolvedParameter
(动态值)
var a = container.Resolve<A>(new NamedParameter("condition", true));
如果您不想显式调用 Resolve
,您可以查看委托 factories(例如 Func<T>
)
我相信你非常接近,你确实需要将 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()));
}