谁首先创建了依赖注入对象

时间:2015-02-19 08:04:00

标签: c# design-patterns mvvm dependency-injection

我想知道谁(哪个对象)创建了依赖注入的真实对象。

为了让我的示例代码

更容易理解

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);
    }
}

就像我们可以看到我是否想要创建一个Orderobject我需要注入一个继承自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)        {        }
}

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

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

这是我的问题,我必须写

var myOrderRepos = new OrderRepository();

这个课程将打破分离......

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

OrderListVM剪掉了

    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();
    }

你会如何避免这种紧密耦合?

1 个答案:

答案 0 :(得分:2)

为什么不在CreateOrder中添加OrderRepository方法?然后你的视图模型会将一个IOrderRepository注入其中,并能够从那里创建订单。

我不会Order取决于IOrderRepository。这似乎是放置依赖关系的错误级别。当你有一个正在进行保存和其他工作的存储库时,将Order之类的对象保存为简单数据容器并将所有操作放在存储库中可以实现清晰的分离。

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

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

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

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);
    }

}

在项目根目录的某处,您将拥有一些引导代码,用于创建ViewModelFactory和其他依赖项的实例,并将它们注入需要它们的类中。