[英]Inversion of Control / Dependency Injection and conversion operators
我有许多MVC应用程序使用的UserModel类,我正在尝试转换为使用IoC:
public class UserModel
{
public string Login { get; set; }
[DisplayName("Display Name")]
public string DisplayName { get; set; }
public static explicit operator UserModel(string userLogin)
{
IKernel IoC; // Where do I get this from?
var ActiveDirRepo = IoC.Get<IActiveDirectoryRepository>();
var User = ActiveDirRepo.FindById<ActiveDirectoryUser>(userLogin.ToUpper());
return new UserModel()
{
Login = userLogin,
DisplayName = User == null ? userLogin.ToUpper() : User.Name
};
}
}
它有一个从string
到UserModel
的显式转换运算符。 以前我只是new
了一个ActiveDirectoryRepository
并使用它,但我想开始使用IoC / DI。
我现在遇到的问题是,如何引用我的IoC容器( IKernel
)?
我不能从外部将它注入UserModel
,因为操作员正在创建它。
您可以使用服务定位器模式表单Microsoft.Practices.ServiceLocation如果ninject不提供实现,我将被取消。 如果不是,那就直接实施了。
无论您是否可以使用此代码执行所需操作,我强烈建议您不要像以前那样实现显式转换运算符。 这是一个不好的做法。
IoC没有什么神奇之处。 有时您仍然需要一个起点,您可以从中获取应用程序的IoC容器,如下所示:
var ioc = Application.Instance.Container.Get<IActiveDirectoryRepository>();
您不需要从任何地方访问IoC容器,因为通过容器创建的对象已经注入了它们的依赖项,但至少有一些根对象需要访问容器。
这种转换假设很简单,这并不需要外部依赖。 如果你需要注入某种依赖,那么忘记转换,没有解决方案。
很简单,将IKernel传递给构建方法:
public static UserModel Build(string userLogin, IKernel IoC)
{
var ActiveDirRepo = IoC.Get<IActiveDirectoryRepository>();
var User = ActiveDirRepo.FindById<ActiveDirectoryUser>(userLogin.ToUpper());
return new UserModel()
{
Login = userLogin,
DisplayName = User == null ? userLogin.ToUpper() : User.Name
};
}
然后你可以问自己这个方法是否属于IKernel接口是否有意义:
interface IKernel
{
UserModel Build(string userLogin);
}
在意识形态上,您的IoC容器应该只存在于应用程序的复合根中。 考虑到这一点,这是一个计算你的类依赖关系并通过构造函数注入它们的问题(如果你不能使用构造函数DI,那么许多IoC容器提供了替代的注入方法)。
在这里,您需要访问IActiveDirectoryRepository
才能创建UserModel。 但是,您的创建方法, explicit operator UserModel
是一个无法访问实例变量的静态方法。 不幸的是,这限制了你使用依赖注入来利用IoC的能力,所以这里有一些想法:
直截了当 :使用服务定位器模式。 您使用服务定位器来获取IActiveDirectoryRepository
的实例。 这将直接适应您当前的实现(将内核行交换到服务定位器)。 但是,这种模式存在缺陷; 最值得注意的是,您正在内化IActiveDirectoryRepository
源,这会使单元测试效率降低。
传统 :将UserModel
创建者放入一个工厂,通过它的构造函数接受IActiveDirectoryRepository
。 然后,工厂创建的任何UserModel
使用提供的IActiveDirectoryRepository
。
public sealed class UserFactory { private readonly IActiveDirecotryRepository repository; public UserFactory(IActiveDirectoryRepository repository) { this.repository = repository; } public UserModel CreateNewUser(string userLogin) { var User = repository.FindById<ActiveDirectoryUser>(userLogin.ToUpper()); return new UserModel() { Login = userLogin, DisplayName = User == null ? userLogin.ToUpper() : User.Name } } }
Fancy :在IActiveDirectoryRepository
创建一个闭包, IActiveDirectoryRepository
创建者作为第一类函数传递。
static Func<string, UserModel> CreateFactory(IActiveDirectoryRepository repository) { return (userLogin) => { var User = repository.FindById<ActiveDirectoryUser>(userLogin.ToUpper()); return new UserModel() { Login = userLogin, DisplayName = User == null ? userLogin.ToUpper() : User.Name } } }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.