public class Foo
{
private IService _service;
public Foo()
{
_service = IocContainer.Resolve<IService>();
}
}
以下是首选的方式(依赖注入)
public class Foo
{
private IService _service;
public Foo(IService service)
{
}
}
现在消费者需要提供服务了。当然,消费者也可以在构造函数中要求IService,但是当层级变得更深时,这似乎很烦人。在某个时刻,有人需要从IoC容器中请求IService——但什么时候呢?
我的一个前同事曾经为UoW/Repository模式编写了一个UnitOfWork类,如下所示(使用Microsoft ServiceLocator):
public static UnitOfWork
{
public static IUnitOfWork Current
{
get { return ServiceLocator.Current.GetInstance<IUnitOfWork>(); }
}
public static void Commit()
{
Current.Commit();
}
public static void Dispose()
{
Current.Dispose();
}
public static IRepository<T> GetRepository<T>() where T : class
{
return ServiceLocator.Current.GetInstance<IRepository>();
}
}
使用 Ninject 连接 IoC,这样对 IRepository 的请求会找到当前的 UoW,如果需要的话会创建一个新的(如果当前的已经被释放)。使用方法如下:
public class MyController
{
public void RunTasks()
{
var rep = UnitOfWork.GetRepository<Tasks>();
var newTasks = from t in rep.GetAll()
where t.IsCompleted == false
select t;
foreach (var task in newTasks)
{
// Do something
}
UnitOfWork.Commit();
}
}
然而,它仍然存在静态IoC(服务定位器)类的问题,但是否有更智能的解决方案呢?在这种情况下,不需要了解内部依赖关系(静态类没有逻辑),并且为了测试目的,备用IoC配置可以使用模拟设置所有内容 - 并且很容易使用。
编辑: 我将尝试通过不同的示例来澄清我的困惑。假设我有一个标准的winforms应用程序,其中包含一个MainWindow类。当用户单击按钮时,我需要从数据库加载一些数据,并将其传递给处理数据的类:
public class MainWindow : Form
{
public MainWindow()
{
}
private void OnUserCalculateClick(object sender, EventArgs args)
{
// Get UoW to connect to DB
// Get instance of processor
}
}
我该如何获取处理器和工作单元的实例?它可以注入到表单类中吗?
我的问题归结为:如果我在一个没有Ioc容器构建的类中,这个类可能是winform、ria服务类等等——是否可以引用服务定位器/IoC控制器来解析依赖项实例,或者有没有更好的处理这些情况的方法?或者是我的做法不对...