【问题标题】:Dependency Injection using Ninject without interface无接口使用 Ninject 进行依赖注入
【发布时间】:2016-06-06 21:48:38
【问题描述】:

我们正在开发一个 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来避免依赖?此外,我们不想创建接口,因为它的范围有限。提前致谢。

【问题讨论】:

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


【解决方案1】:

从表示层抽象出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(...) { ... }
}

这样做的好处是您可以保持表示层较薄,但与其他方法相比,所示方法仍有相当多的缺点。如here 所述,其中一种替代方法是使用基于消息的方法和 SOLID 设计。

【讨论】:

    【解决方案2】:

    如果我理解您的问题,您应该创建中间业务层以将 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
       }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-07-31
      • 1970-01-01
      • 2011-04-06
      • 2012-05-03
      • 2011-03-23
      • 2020-12-04
      • 1970-01-01
      • 2012-03-15
      相关资源
      最近更新 更多