使用Ninject进行依赖注入而不使用接口

时间:2016-06-01 03:53:04

标签: c# asp.net-mvc dependency-injection ninject

我们正在开发一个Mvc应用程序,我们希望使用nInject来使用依赖注入。目前我们正在维护不同类库“ShopEntities”中的实体,而在我们的mvc应用程序中,我们正在使用这些实体。 让我们考虑ShopEntities中的一个类。

namespace ShopEntities
{
    public class Customers
    {
        public int custId {get;set;}

        public string custName {get;set;}
        public string Address {get;set;}
        public string ShippingAddress {get;set;}

    }
}

现在,当我们想在我们的mvc应用程序中使用它时,我们创建一个实例并设置如下所示的属性,

public ActionResult Index()
{
    ShopEntities.Customers cust = new ShopEntities.Customers();
    cust.CustName = "Sam";
    cust.IAddress = "xyz";
    cust.ShippingAddress = "xyz xyx xyz"; 

}

如何在这里使用nInject来避免依赖?此外,我们不希望创建接口,因为这在范围上是有限的。提前谢谢。

2 个答案:

答案 0 :(得分:5)

从表示层抽象出Customer实体的使用的方法不是将实体本身隐藏在某种ICustomer之后,也不是让DI容器构建它。隐藏接口后面的数据对象通常没有用;接口用于抽象行为,而不是数据。

由于NightOwl已经stated,您的Customer实体是运行时数据,您使用容器来构建包含运行时数据的对象图。

相反,您应该隐藏抽象背后的特定业务操作。这种抽象可以由表示层使用并由业务层实现。例如:

public interface ICustomerServices
{
    void CreateCustomer(string customerName, string homeAddress, 
        string shippingAddress);

    void ChangeShippingAddress(Guid customerId, string shippingAddress);
}

你的控制器可以依赖这种抽象:

private readonly ICustomerServices customerServices;

public CustomerController(ICustomerServices customerServices) {
    this.customerServices = customerServices;
}

public ActionResult Index()
{
    this.customerServices.CreateCustomer("Sam", "xyz", "xyz xyz xyz");
}

现在,您的业务层可以为此抽象创建一个实现,该实现在内部使用实体:

public class CustomerServices : ICustomerServices
{
    private readonly EntitiesContext context;

    public CustomerServices(EntitiesContext context) {
        this.context = context;
    }

    public void CreateCustomer(string customerName, string homeAddress,
        string shippingAddress)
    {
        // NOTE that I renamed 'Customers' to 'Customer', since it holds information
        // to only one customer. 'Customers' implies a collection.
        Customer cust = new ShopEntities.Customer();
        cust.CustName = "Sam";
        cust.IAddress = "xyz";
        cust.ShippingAddress = "xyz xyx xyz"; 

        this.context.Customers.Add(cust);

        this.context.SubmitChanges();
    }

    public void ChangeShippingAddress(...) { ... }
}

这样做的好处是,您可以保持表现层薄,但与替代方案相比,所显示的方法仍有一些不利因素。其中一种替代方案是使用基于消息的方法和SOLID设计,如here所述。

答案 1 :(得分:0)

如果我理解你的问题,你应该创建中间业务层,将ShopEntities转换为你自己的实体:

namespace MyShopEntities
{
    public class MyCustomers
    {
        public int custId {get;set;}

        public string custName {get;set;}
        public string Address {get;set;}
        public string ShippingAddress {get;set;}

    }
}

public ActionResult Index()
{
    ShopEntities.Customers cust = new MyShopEntities.MyCustomers();
    cust.CustName = "Sam";
    cust.IAddress = "xyz";
    cust.ShippingAddress = "xyz xyx xyz"; 

}

class BussinesModel
{
   void Insert(ShopEntities.Customer customer)
   {
     // use ShopEntities.Customer only in wrapper
     // if you later switch to another Customer dependency,
     // you just change this     wrapper

     MyShopEntities.MyCustomers cust = new MyShopEntities.MyCustomers();
     cust.CustName = customer.CustName;
     cust.IAddress = customerIAddress;
     cust.ShippingAddress = customer.ShippingAddress; 
     InsertInternal(cust);
   }

   void InsertInternal(MyShopEntities.MyCustomer customer)
   {
       // use MyCustomer for all your bussines logic
   }
}