Ste*_*ght 10 .net c# dependency-injection inversion-of-control
这个问题是Jeffery Palermo关于如何解决分支代码和依赖注入问题的结果http://jeffreypalermo.com/blog/constructor-over-injection-anti-pattern/
在他的帖子中,Jeffery有一个class(public class OrderProcessor : IOrderProcessor),在构造函数上有2个接口.一个是验证器IOrderValidator和IOrderShipper接口.他的方法代码只在IOrderValidator接口上使用方法后才会分支,从不在IOrderShipper接口上使用任何东西.
他建议创建一个工厂,调用静态方法来获取接口的委托.他正在重构的代码中创建一个新对象,这似乎是不必要的.
我想问题的关键在于我们使用IoC来构建所有对象,无论它们是否被使用. 如果您实例化一个具有2个接口的对象并且具有可以分支以不使用其中一个的代码,那么您如何处理它?
在这个例子中,我们假设_validator.Validate(order)always总是返回false,并且IOrderShipper.Ship()永远不会调用该方法.
原始代码:
public class OrderProcessor : IOrderProcessor
{
private readonly IOrderValidator _validator;
private readonly IOrderShipper _shipper;
public OrderProcessor(IOrderValidator validator, IOrderShipper shipper)
{
_validator = validator;
_shipper = shipper;
}
public SuccessResult Process(Order order)
{
bool isValid = _validator.Validate(order);
if (isValid)
{
_shipper.Ship(order);
}
return CreateStatus(isValid);
}
private SuccessResult CreateStatus(bool isValid)
{
return isValid ? SuccessResult.Success : SuccessResult.Failed;
}
}
public class OrderShipper : IOrderShipper
{
public OrderShipper()
{
Thread.Sleep(TimeSpan.FromMilliseconds(777));
}
public void Ship(Order order)
{
//ship the order
}
}
Run Code Online (Sandbox Code Playgroud)
重构代码
public class OrderProcessor : IOrderProcessor
{
private readonly IOrderValidator _validator;
public OrderProcessor(IOrderValidator validator)
{
_validator = validator;
}
public SuccessResult Process(Order order)
{
bool isValid = _validator.Validate(order);
if (isValid)
{
IOrderShipper shipper = new OrderShipperFactory().GetDefault();
shipper.Ship(order);
}
return CreateStatus(isValid);
}
private SuccessResult CreateStatus(bool isValid)
{
return isValid ? SuccessResult.Success : SuccessResult.Failed;
}
}
public class OrderShipperFactory
{
public static Func<IOrderShipper> CreationClosure;
public IOrderShipper GetDefault()
{
return CreationClosure(); //executes closure
}
}
Run Code Online (Sandbox Code Playgroud)
这是在启动时配置此工厂的方法(ASP.NET的global.asax):
private static void ConfigureFactories()
{
OrderShipperFactory.CreationClosure =
() => ObjectFactory.GetInstance<IOrderShipper>();
}
Run Code Online (Sandbox Code Playgroud)
Mar*_*ann 22
我刚刚发布了Jeffrey Palermos帖子的反驳.
简而言之,我们不应该让具体的实施细节影响我们的设计.这将违反建筑规模上的Liskov替代原则.
更优雅的解决方案让我们通过引入延迟加载OrderShipper来保持设计.