使用哪种依赖注入 "factory"?
Which dependency injection "factory" to use?
我有两个选项可以创建 ViewModel 工厂以注入其他 classes:
选项A
public interface IFactory
{
ViewModelA CreateViewModelA(string data);
ViewModelB CreateViewModelB(string data);
}
public class MyFactory : IFactory
{
public MyFactory(){}
public ViewModelA CreateViewModelA(string data)
{
return new ViewModelA (data);
}
public ViewModelA CreateViewModelB(string data)
{
return new ViewModelB (data);
}
}
//register factory
container.RegisterType<IFactory, MyFactory>(new ContainerControlledLifetimeManager());
选项 B
public interface IFactory
{
T CreateViewModel<T>();
}
public class MyFactory : IFactory
{
public MyFactory(IUnityContainer unityContainer)
{
_container = unityContainer;
}
private IUnityContainer _container { get; set; }
public T CreateViewModel<T>()
{
return (T)this._container.Resolve<T>();
}
}
//register factory
var container = new UnityContainer();
container.RegisterType<IFactory, MyFactory>(new ContainerControlledLifetimeManager(), new InjectionConstructor(container));
//inject this where neccessary
选项B似乎更容易实现,但是我不确定以这种方式使用容器是否正确。我已经阅读了有关服务定位器反模式的信息,在这种情况下,我将容器传递给另一个 class 的构造函数的方式似乎类似于这个问题。那么我应该选择哪个选项,如果可能的话请详细说明,为什么?
支持选项 A 原因有很多:
首先,在选项 B 中,MyFactory
并没有真正做任何事情。即使 return (T)this._container.Resolve<T>();
中的通用转换也是多余的,所以现在它只是一个 Adapter over IUnityContainer
. In all the code where you'd depend on the B version of IFactory
, you could just as well depend directly on IUnityContainer
(ignoring the Interface Segregation Principle。
其次,IUnityContainer
(因此也是选项 B)是 Service Locator, which is an anti-pattern. One problem is that it offers an infinity of methods that you can call at compile time, but which will fail at run time. It also violates encapsulation。
另一方面,选项 A isn't a Service Locator。它只提供有限的API。不过,我可能会改用通用接口:
public interface IFactory<T>
{
T Create(object context);
}
你有 various options for how you want to implement the interface, but keep in mind that software development productivity doesn't have much to do with how long it takes to type 东西。不应该决定哪个替代方案最容易实现,而应该决定哪个版本产生的代码最容易理解。
您阅读代码的时间比编写代码的时间多得多。
我有两个选项可以创建 ViewModel 工厂以注入其他 classes:
选项A
public interface IFactory
{
ViewModelA CreateViewModelA(string data);
ViewModelB CreateViewModelB(string data);
}
public class MyFactory : IFactory
{
public MyFactory(){}
public ViewModelA CreateViewModelA(string data)
{
return new ViewModelA (data);
}
public ViewModelA CreateViewModelB(string data)
{
return new ViewModelB (data);
}
}
//register factory
container.RegisterType<IFactory, MyFactory>(new ContainerControlledLifetimeManager());
选项 B
public interface IFactory
{
T CreateViewModel<T>();
}
public class MyFactory : IFactory
{
public MyFactory(IUnityContainer unityContainer)
{
_container = unityContainer;
}
private IUnityContainer _container { get; set; }
public T CreateViewModel<T>()
{
return (T)this._container.Resolve<T>();
}
}
//register factory
var container = new UnityContainer();
container.RegisterType<IFactory, MyFactory>(new ContainerControlledLifetimeManager(), new InjectionConstructor(container));
//inject this where neccessary
选项B似乎更容易实现,但是我不确定以这种方式使用容器是否正确。我已经阅读了有关服务定位器反模式的信息,在这种情况下,我将容器传递给另一个 class 的构造函数的方式似乎类似于这个问题。那么我应该选择哪个选项,如果可能的话请详细说明,为什么?
支持选项 A 原因有很多:
首先,在选项 B 中,MyFactory
并没有真正做任何事情。即使 return (T)this._container.Resolve<T>();
中的通用转换也是多余的,所以现在它只是一个 Adapter over IUnityContainer
. In all the code where you'd depend on the B version of IFactory
, you could just as well depend directly on IUnityContainer
(ignoring the Interface Segregation Principle。
其次,IUnityContainer
(因此也是选项 B)是 Service Locator, which is an anti-pattern. One problem is that it offers an infinity of methods that you can call at compile time, but which will fail at run time. It also violates encapsulation。
另一方面,选项 A isn't a Service Locator。它只提供有限的API。不过,我可能会改用通用接口:
public interface IFactory<T>
{
T Create(object context);
}
你有 various options for how you want to implement the interface, but keep in mind that software development productivity doesn't have much to do with how long it takes to type 东西。不应该决定哪个替代方案最容易实现,而应该决定哪个版本产生的代码最容易理解。
您阅读代码的时间比编写代码的时间多得多。