谁首先创建依赖注入对象 [英] Who creates dependency injection object in the first place

查看:135
本文介绍了谁首先创建依赖注入对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



为了让我们更容易理解,我的示例代码



IOrder

 界面IOrder 
{
int Id {get;组; }
string Name {get;组; }
bool SaveChanges();
}

订单 / p>

  public class Order:IOrder 
{
private IOrderRepository repository;

public int Id {get;组; }
public string Name {get;组;

public Order(IOrderRepository存储库)
{
this.repository = repository;
}

public bool SaveChanges()
{
if(Id< 1)
return repository.Save(this);
else
return repository.Update(this);
}
}

我们可以看到我是否要创建一个Orderobject我需要注入一个继承自 IOrderRepository



IOrderRepository

 界面IOrderRepository 
{
IList< IOrder>得到所有();
IOrder GetById(int id);
IList< IOrder> GetBySomeRefId(int SomeRefId);
bool Save(IOrder order);
bool更新(IOrder顺序);
}

OrderRepository / p>

  public class OrderRepository:IOrderRepository 
{
public IList< IOrder> GetAll(){}

public IOrder GetById(int id){}

public IList< IOrder> GetBySomeRefId(int SomeRefId){}

public bool Save(IOrder order){}

public bool更新(IOrder顺序){}
}

所以这里每个 Get 方法可以并将注入一个类作为依赖,
但如果我需要一个新的订单我必须做

  var myOrderRepos = new OrderRepository(); 
var myNewOrder = new Order(myorderrepos);

这里是我的问题,我必须写下

  var myOrderRepos = new OrderRepository(); 

此课程将打破分离...



这个基本上每个ViewModel都有一个新的命令,在这种情况下 NewOrderCommand



OrderListVM 剪切

  public ICommand NewOrderCommand 
{
get {return newOrderCommand? (newOrderCommand = new RelayCommand(param => this.OnNewOrder()));
}

public void OnNewOrder()
{
var myOrderRepos = new OrderRepository(); //< =紧耦合到OrderRepository
var myNewOrder = new Order(myorderrepos); //< =紧耦合到Order
var myOrderVM = new OrderVM(myNewOrder);
myOrderVM.Show();
}

你如何避免这种紧耦合?

解决方案

为什么不在 OrderRepository CreateOrder C>?那么你的视图模型会得到一个IOrderRepository注入到它们中,并可以从那里创建订单。



我不会使订单依赖于 IOrderRepository 。这似乎是错位的依赖关系。当您有一个正在进行保存和其他工作的存储库时,将像Order这样的对象作为简单的数据容器保留在存储库中,并将所有操作放在存储库中提供了一个干净的分离。



我发现使用依赖注入(特别是与存储库结合使用)时,我的视图模型和控制器代码很少包含新的关键字。



依赖注入是一种用于管理耦合的模式。正如marc_s在他的评论中指出的,你想依赖于抽象而不是实现。你的类有依赖关系是可以的,但是如果每个依赖关系的接口被赋予给你的类,而不是你的类创建自己的版本的依赖关系的实现,那就更好了。这就是为什么我在课堂上看不到 new 的原因。我知道如果我正在添加一个对象,那么这可能是一个很好的地方停止,并确定如何将该依赖关系传递到类中,而不是在那里创建它。当然,创建数据对象管理新的实例的存储库是调用新的的好地方。



这里有一些代码来帮助解释我在说什么。在注意到,在 OrderListVM 中创建 OrderVM 实例。所以,我已经从VM中的 IOrderRepository 依赖,并引入了一个ViewModel工厂。您可能还需要一个 RepositoryFactory ,但这似乎太多了。



IOrder

  interface IOrder 
{
int Id {get;组; }
string Name {get;组;
}

订单

  public class Order:IOrder 
{
public int Id {get;组; }
public string Name {get;组;
}

IOrderRepository

 界面IOrderRepository 
{
IList< IOrder>得到所有();
IOrder GetById(int id);
IList< IOrder> GetBySomeRefId(int SomeRefId);
bool Save(IOrder order);
bool更新(IOrder顺序);
IOrder CreateNewOrder();
}

OrderRepository / p>

  public class OrderRepository:IOrderRepository 
{
...
public IOrder CreateNewOrder()
{
返回新的Order();
}
}

OrderListVM

  public class OrderListVM 
{

ViewModelFactory _factory;
IEnumerable< IOrder> _orderList;

public OrderListVM(ViewModelFactory factory,IEnumerable< IOrder> orders)
{
_factory = factory;
_orderList = orders;
}

public void OnNewOrder()
{
var myOrderVM = _factory.GetOrderVM();
myOrderVM.Show();
}
}

OrderVM

  public class OrderVM 
{
IOrder _order;
public OrderVM(IOrder order)
{
_order = order;
}
}

ViewModelFactory

 界面IViewModelFactory {...} 

public class ViewModelFactory:IViewModelFactory
{
IOrderRepository _repository;

public ViewModelFactory(IOrderRepository repo)
{
_repository = repo;
}

public OrderListVM GetOrderListVM(){
返回新的OrderListVM(this,_repository.GetAll());
}

public OrderVM GetOrderVM(IOrder order = null){
if(order == null){
order = _repository.CreateNewOrder();
}
返回新的OrderVM(order);
}

}

在项目的根部您将有一些引导代码创建一个 ViewModelFactory 和其他依赖关系的实例,并将它们注入到需要它们的类中。


I would like to know who (which object) creates the real object which gets dependeny injected.

To make it more understandable here my example code

IOrder:

interface IOrder
{
    int Id { get; set; }
    string Name { get; set; }
    bool SaveChanges();
}

Order:

public class Order : IOrder
{
    private IOrderRepository repository;

    public int Id { get; set; }
    public string Name { get; set; }

    public Order(IOrderRepository repository)
    {
        this.repository = repository;
    }

    public bool SaveChanges()
    {
        if (Id < 1)
            return repository.Save(this);
        else
            return repository.Update(this);
    }
}

Like we can see if i want to create an Orderobject i need to inject an some object which inherited from IOrderRepository

IOrderRepository:

interface IOrderRepository
{
    IList<IOrder> GetAll();
    IOrder GetById(int id);
    IList<IOrder> GetBySomeRefId(int SomeRefId);
    bool Save(IOrder order);
    bool Update(IOrder order);
}

OrderRepository:

public class OrderRepository : IOrderRepository
{
    public IList<IOrder> GetAll()        {        }

    public IOrder GetById(int id)        {        }

    public IList<IOrder> GetBySomeRefId(int SomeRefId)        {        }

    public bool Save(IOrder order)        {        }

    public bool Update(IOrder order)        {        }
}

So here each Get method can and will inject it one class as a dependency, but if I need a new Order I have to do

var myOrderRepos = new OrderRepository();
var myNewOrder = new Order(myorderrepos);

and here is my problem where ever I have to write the

var myOrderRepos = new OrderRepository();

this class will break the separation ...

And this will basically every ViewModel which has a new command in it in this case NewOrderCommand.

OrderListVM snipped

    public ICommand NewOrderCommand
    {
        get { return newOrderCommand ?? (newOrderCommand = new RelayCommand(param => this.OnNewOrder())); }
    }

    public void OnNewOrder()
    {
        var myOrderRepos = new OrderRepository(); // <= tight coupling to OrderRepository
        var myNewOrder = new Order(myorderrepos); // <= tight coupling to Order
        var myOrderVM = new OrderVM(myNewOrder);
        myOrderVM.Show();
    }

How would you avoid this tight coupling?

解决方案

Why not put a CreateOrder method in your OrderRepository? Then your view models would get an IOrderRepository injected into them and be able to create orders from there.

I wouldn't make Order depend on IOrderRepository. That seems like the wrong level to place the dependency. When you've got a repository that's doing the saving and other work, then keeping objects like Order as simple data containers and putting all the actions in the repository provides a clean separation.

I find when using dependency injection (especially when combined with repositories), my view model and controller code very rarely contains the new keyword.

Dependency Injection is a pattern for managing coupling. As marc_s points out in his comment, you want to depend on the abstractions, not the implementations. It's OK for your classes to have dependencies, but it's better if the interface for each dependency is given to your class than for your class to create its own version of the implementation of that dependency. That's why I don't see new in my classes. I know if I'm newing up an object then that's probably a good place to stop and identify how to pass that dependency into the class instead of creating it right there. Of course, a repository creating new instances of the data object it manages is a good place for a call to new.

Here's some code to try to help explain what I'm talking about. While working through this, I noticed you're creating OrderVM instances within your OrderListVM. So, I've taken the dependency on IOrderRepository out of the VMs and introduced a ViewModel factory. You may also want a RepositoryFactory, but that seemed like too much to show here.

IOrder:

interface IOrder
{
    int Id { get; set; }
    string Name { get; set; }
}

Order:

public class Order : IOrder
{
    public int Id { get; set; }
    public string Name { get; set; }
}

IOrderRepository:

interface IOrderRepository
{
    IList<IOrder> GetAll();
    IOrder GetById(int id);
    IList<IOrder> GetBySomeRefId(int SomeRefId);
    bool Save(IOrder order);
    bool Update(IOrder order);
    IOrder CreateNewOrder();
}

OrderRepository:

public class OrderRepository : IOrderRepository
{
    ...
    public IOrder CreateNewOrder()
    {
        return new Order();
    }
}

OrderListVM:

public class OrderListVM 
{

    ViewModelFactory _factory;
    IEnumerable<IOrder> _orderList;

    public OrderListVM(ViewModelFactory factory, IEnumerable<IOrder> orders)
    {
        _factory = factory;
        _orderList = orders;
    }

    public void OnNewOrder()
    {
        var myOrderVM = _factory.GetOrderVM();
        myOrderVM.Show();
    }
}

OrderVM

public class OrderVM 
{
    IOrder _order;
    public OrderVM(IOrder order)
    {
        _order = order;
    }
}

ViewModelFactory

interface IViewModelFactory { ... }

public class ViewModelFactory : IViewModelFactory 
{
    IOrderRepository _repository;

    public ViewModelFactory (IOrderRepository repo)
    {
        _repository = repo;
    }

    public OrderListVM GetOrderListVM() {
        return new OrderListVM(this, _repository.GetAll());
    }

    public OrderVM GetOrderVM(IOrder order = null) {
        if (order == null) {
            order = _repository.CreateNewOrder();
        }
        return new OrderVM(order);
    }

}

Somewhere at the root of your project you'll have some bootstrap code that creates an instance of the ViewModelFactory and other dependencies and injects them into the classes that need them.

这篇关于谁首先创建依赖注入对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆