Dependency injection 与接口、工厂和控制反转混淆
使用接口是删除依赖项的一种非常简单的方法,但是当您的一个类需要一个接口未定义的方法时会发生什么?如果您使用的是构造函数注入或工厂,那么如何在不强制转换的情况下访问该额外方法?这可能吗 下面是一个有这个问题的工厂的例子。我是在尝试做一些不可能的事情吗?谢谢你的帮助Dependency injection 与接口、工厂和控制反转混淆,dependency-injection,inversion-of-control,interface,factory,Dependency Injection,Inversion Of Control,Interface,Factory,使用接口是删除依赖项的一种非常简单的方法,但是当您的一个类需要一个接口未定义的方法时会发生什么?如果您使用的是构造函数注入或工厂,那么如何在不强制转换的情况下访问该额外方法?这可能吗 下面是一个有这个问题的工厂的例子。我是在尝试做一些不可能的事情吗?谢谢你的帮助 interface IFoo { int X { get; set; } int Y { get; set; } } public class A : IFoo { int X { get; set; }
interface IFoo {
int X { get; set; }
int Y { get; set; }
}
public class A : IFoo {
int X { get; set; }
int Y { get; set; }
}
public class B : IFoo {
int X { get; set; }
int Y { get; set; }
int Z { get; set; }
}
public static class FooFactory {
public static IFoo GetFoo(string AorB) {
IFoo result = null;
switch (AorB) {
case "A":
result = new A();
break;
case "B":
result = new B();
break;
}
return result;
}
}
public class FooContainer {
private IFoo foo;
public FooContainer(IFoo foo) {
this.foo = foo;
}
/* What methods would you define here. I'm new to IoC. */
}
public class Main(...) {
int x,y,z;
IFoo fooA = FooFactory.GetFoo("A");
x = foo.X;
y = foo.Y;
IFoo fooB = FooFactory.GetFoo("B");
x = foo.X;
y = foo.Y;
z = foo.Z; /* Does not compile */
z = ((B)foo).Z; /* Compiles, but adds unwanted dependency */
}
你确实需要施展才华。这是正常的,有时是必要的。不过,这通常是有问题的迹象 理想情况是,如果一个方法/例程获取/返回一个接口,那么您的逻辑只关心该接口公开的成员。如果在该方法中,您发现自己正在检查确切的类型,以便可以强制转换为该类型,并根据类型调用不同的成员,那么可能是出了问题 假设您有一个IContact接口,实现该接口的一些实体是您的类Customer、Purchaser和Contractor。如果您的SendChristmasCard方法采用IContact,那么它应该只关心IContact成员。如果此方法中的逻辑正在对
obj.GetType().ToString
执行select Case以确定它是否是客户,则:
但是,请查看该方法,它在这种情况下会有所帮助。如果您试图访问接口不可用的方法,请不要使用工厂。显然,您正在对依赖项进行硬编码……所以只需使用它(,但只有在确实需要时才使用它) 没有必要把事情复杂化
试图回溯到对象类型而不是接口将引入依赖项…但它将隐藏它而不是公开依赖项。如果将来有人更改了工厂,并且您的调用返回了不同的对象类型,那么您的代码现在将以一种不明显的方式中断。当您遇到向下转换对象的需要时,这通常是API可能更好的迹象 向下转换抽象类型违反了。通常,最好通过更改相关接口的样式来解决此问题。与其公开大量的属性和查询(术语上),不如将重点转向更面向命令的方法。这是最新的 您不必让
IFoo
公开X和Y属性,而是可以针对一组命令重新定义其行为:
public interface IFoo
{
void DoStuff();
void DoSomethingElse(string bar);
void DoIt(DateTime now);
}
然后,具体的实现可以封装他们想要的任何数据(如X、Y或Z属性),而无需消费者了解它们
当接口变得太大时,是时候应用或了。这是一个泄漏的抽象、缺乏封装和/或违反单一责任原则。换句话说,如果你的代码是以这种方式设计的,那么它就是你代码中的一个设计问题,你应该重新构造它,使它不需要在这个上下文中调用额外的方法。我遇到的问题不是“方法”本身,而是额外的属性。我们当前的解决方案是让接口包含属性的说明。这样,实现类可以包含它们所需的任何属性,而不会破坏接口。我只是希望有一个聪明的方法不用字典就能做到这一点。谢谢,这真的很有帮助。事实上,这是我已经开始遵循的模式。我喜欢引用坚实的原则。