C# Unity:告诉容器在注册类型时始终使用接口的特定实现
我一直遇到这种情况:假设我有接口C# Unity:告诉容器在注册类型时始终使用接口的特定实现,c#,inversion-of-control,unity-container,C#,Inversion Of Control,Unity Container,我一直遇到这种情况:假设我有接口IFoo和几个实现,比如RedFoo:IFoo和BlackFoo:IFoo。然后,我在构造函数中使用IFoo的类: class BlackFooUser { public BlackFooUser(IFoo foo, other_parameters_here) {...} } class RedFooUser { public RedFooUser(IFoo foo, other_parameters_here) {...} } public c
IFoo
和几个实现,比如RedFoo:IFoo
和BlackFoo:IFoo
。然后,我在构造函数中使用IFoo
的类:
class BlackFooUser
{
public BlackFooUser(IFoo foo, other_parameters_here) {...}
}
class RedFooUser
{
public RedFooUser(IFoo foo, other_parameters_here) {...}
}
public class BlackFooUser
{
public BlackFooUser([Dependency(BlackFoo.UNITY_KEY)] IFoo foo)
{
}
}
如何告诉容器像往常一样解析所有其他参数,但在构造blackfoooser
时始终使用BlackFoo
,在构造redfoooser
时始终使用RedFoo
?我知道我可以在调用Resolve()
时使用ParameterOverride
,但我希望在解析Red/blackfooouser
时使用相同的参数,因此这应该进入RegisterType
或RegisterFactory
我可以做类似的事情
container.RegisterFactory<RedFooUser>(c=>new RedFooUser(c.Resolve<RedFoo>(), other_parameters_here));
container.RegisterFactory(c=>newRedFooUser(c.Resolve(),此处为其他参数));
但这是相当冗长的,每次我添加新参数时都必须更改
有更好的办法吗
更新我特别希望通过容器注册做到这一点,而不修改涉及的类。原因有很多,但归结起来就是:
- 在类中编码依赖信息违反了关注点分离
- 在有许多类和许多依赖项的情况下,它通常伸缩性很差
- 它限制了类的组合方式
- 它将我限制为拥有源代码的类,并且可以随意修改
public abstract class FooUser<TFoo> where TFoo : IFoo
{
private readonly TFoo _foo;
public FooUser(TFoo foo, other parameters)
{
_foo = foo;
}
}
public class BlackFooUser : FooUser<BlackFoo>
{
public BlackFooUser (BlackFoo foo, other parameters)
: base(foo, other parameters)
{
}
}
public class RedFooUser : FooUser<RedFoo>
{
public RedFooUser (RedFoo foo, other parameters)
: base(foo, other parameters)
{
}
}
公共抽象类fooouser其中TFoo:IFoo
{
私有只读TFOOfoo;
公共FooUser(TFoo foo,其他参数)
{
_foo=foo;
}
}
公共类BlackFooUser:FooUser
{
公共BlackFooUser(BlackFoo-foo,其他参数)
:base(foo,其他参数)
{
}
}
公共类RedFooUser:FooUser
{
公共redfoooser(RedFoo-foo,其他参数)
:base(foo,其他参数)
{
}
}
完整复制如下-输出为:
使用foo'RedFoo'和其他参数'I'm the other'构造RedFooUser
使用foo'BlackFoo'和其他参数'I'm the other'构造BlackFooUser
void Main()
{
var container=newunitycontainer()
.RegisterInstance(“我是另一个参数”);
var foo1=container.Resolve();
var foo2=container.Resolve();
}
//定义其他方法、类和
公共接口IFoo
{
}
公共类BlackFoo:IFoo{}
公共类RedFoo:IFoo{}
公共抽象类FooUser,其中TFoo:IFoo
{
私有只读TFOOfoo;
公共FooUser(TFoo foo,字符串其他参数)
{
_foo=foo;
WriteLine($“用foo'{foo.GetType().Name}'和otherParameter'{otherParameter}'构造了{GetType().Name}”);
}
}
公共类BlackFooUser:FooUser
{
公共BlackFooUser(BlackFoo-foo,字符串其他参数)
:base(foo,其他参数)
{
}
}
公共类RedFooUser:FooUser
{
公共RedFooUser(RedFoo-foo,字符串其他参数)
:base(foo,其他参数)
{
}
}
使用抽象类和泛型强制特定类型
Unity将自动解析一个具体类型,因此您不需要注册这些类型
public abstract class FooUser<TFoo> where TFoo : IFoo
{
private readonly TFoo _foo;
public FooUser(TFoo foo, other parameters)
{
_foo = foo;
}
}
public class BlackFooUser : FooUser<BlackFoo>
{
public BlackFooUser (BlackFoo foo, other parameters)
: base(foo, other parameters)
{
}
}
public class RedFooUser : FooUser<RedFoo>
{
public RedFooUser (RedFoo foo, other parameters)
: base(foo, other parameters)
{
}
}
公共抽象类fooouser其中TFoo:IFoo
{
私有只读TFOOfoo;
公共FooUser(TFoo foo,其他参数)
{
_foo=foo;
}
}
公共类BlackFooUser:FooUser
{
公共BlackFooUser(BlackFoo-foo,其他参数)
:base(foo,其他参数)
{
}
}
公共类RedFooUser:FooUser
{
公共redfoooser(RedFoo-foo,其他参数)
:base(foo,其他参数)
{
}
}
完整复制如下-输出为:
使用foo'RedFoo'和其他参数'I'm the other'构造RedFooUser
使用foo'BlackFoo'和其他参数'I'm the other'构造BlackFooUser
void Main()
{
var container=newunitycontainer()
.RegisterInstance(“我是另一个参数”);
var foo1=container.Resolve();
var foo2=container.Resolve();
}
//定义其他方法、类和
公共接口IFoo
{
}
公共类BlackFoo:IFoo{}
公共类RedFoo:IFoo{}
公共抽象类FooUser,其中TFoo:IFoo
{
私有只读TFOOfoo;
公共FooUser(TFoo foo,字符串其他参数)
{
_foo=foo;
WriteLine($“用foo'{foo.GetType().Name}'和otherParameter'{otherParameter}'构造了{GetType().Name}”);
}
}
公共类BlackFooUser:FooUser
{
公共BlackFooUser(BlackFoo-foo,字符串其他参数)
:base(foo,其他参数)
{
}
}
公共类RedFooUser:FooUser
{
公共RedFooUser(RedFoo-foo,字符串其他参数)
:base(foo,其他参数)
{
}
}
注册类型时,可以给它们一个名称,然后在注入这些类型的构造函数中引用该名称。大概是这样的:
public class BlackFoo : IFoo
{
public const string UNITY_KEY = "BlackFoo";
}
在您的容器注册中:
_container.RegisterType<IFoo, BlackFoo>(BlackFoo.UNITY_KEY, new ContainerControlledLifetimeManager());
这确保了当容器进行依赖项注入时,它将使用命名的
IFoo
注册。当您注册类型时,您可以给它们一个名称,然后在注入这些类型的构造函数中引用该名称。大概是这样的:
public class BlackFoo : IFoo
{
public const string UNITY_KEY = "BlackFoo";
}
在您的容器注册中:
_container.RegisterType<IFoo, BlackFoo>(BlackFoo.UNITY_KEY, new ContainerControlledLifetimeManager());
这确保了当容器进行依赖项注入时,它将使用命名的IFoo
注册。我提交给UnityContainer repo,Eugene Sadovoy的响应将我推向了这个答案
为了避免无限循环,可以注册默认fa