Jon*_*Jon 10 .net c# design-patterns dependency-injection inversion-of-control
我对实现相同接口和依赖注入的2个类的场景感到困惑.
public interface ISomething
{
void DoSomething();
}
public class SomethingA : ISomething
{
public void DoSomething()
{
}
}
public class SomethingAB : ISomething
{
public void DoSomething()
{
}
}
public class Different
{
private ISomething ThisSomething;
public Different(ISomething Something)
{
ThisSomething = Something;
}
}
Run Code Online (Sandbox Code Playgroud)
我已经看到在线示例说这是有效的,但你一次只能使用一个类.因此,如果应用程序在SiteA运行,您告诉您的IOC使用SomethingA,但如果它在SiteB,您告诉它使用SomethingAB.
因此,有一个应用程序有2个类实现1个接口,并尝试使用这两个类,这被认为是不好的做法吗?如果不是你怎么告诉国际奥委会在相关情况下使用哪个班级?
更新:为了更好地解释它,我将使用Ninject的例子:
public class Samurai
{
private IWeapon Weapon;
public Samurai(IWeapon weapon)
{
this.Weapon = weapon;
}
}
public class Sword : IWeapon
{
...
}
public class Gun : IWeapon
{
...
}
public class WarriorModule : NinjectModule
{
public override void Load()
{
this.Bind<IWeapon>().To<Sword>();
this.Bind<IWeapon>().To<Gun>(); //Just an example
}
}
Run Code Online (Sandbox Code Playgroud)
所以现在你有两个使用IWeapon的类.根据您应用中的某些内容或背景,您希望Samurai有时会使用剑或在其他点使用枪.你是怎么做到这一点的?你如何处理"if"场景?
Dar*_*rov 13
我不认为这在一般情况下是不好的做法.在某些情况下,您可能需要在同一个应用程序中使用相同接口的不同实现,并且基于上下文使用一个或另一个实现
至于如何配置你的DI以启用这个场景,当然,它将取决于你的DI :-)有些人可能不支持它,其他人可能不支持,其他人可能部分支持它等等.
例如,使用Ninject,您可以拥有以下类:
public interface ISomething
{
}
public class SomethingA : ISomething
{
}
public class SomethingB : ISomething
{
}
public class Foo
{
public Foo(ISomething something)
{
Console.WriteLine(something);
}
}
public class Bar
{
public Bar(ISomething something)
{
Console.WriteLine(something);
}
}
Run Code Online (Sandbox Code Playgroud)
然后在配置内核时使用命名绑定:
// We create the kernel that will be used to provide instances when required
var kernel = new StandardKernel();
// Declare 2 named implementations of the same interface
kernel.Bind<ISomething>().To<SomethingA>().Named("somethingA");
kernel.Bind<ISomething>().To<SomethingB>().Named("somethingB");
// inject SomethingA into Foo's constructor
kernel.Bind<Foo>().ToSelf().WithConstructorArgument(
"something", ctx => ctx.Kernel.Get<ISomething>("somethingA")
);
// inject SomethingB into Bar's constructor
kernel.Bind<Bar>().ToSelf().WithConstructorArgument(
"something", ctx => ctx.Kernel.Get<ISomething>("somethingB")
);
Run Code Online (Sandbox Code Playgroud)
现在当你请求Foo它的一个实例时,它会SomethingA向它注入它的构造函数,当你请求Bar它的实例时会注入SomethingB它:
var foo = kernel.Get<Foo>();
var bar = kernel.Get<Bar>();
Run Code Online (Sandbox Code Playgroud)