使用 Ninject 没有接口的依赖注入
Dependency Injection using Ninject without interface
我们正在开发一个 Mvc 应用程序,我们希望在其中使用 nInject 来使用依赖注入。目前我们在不同的 class 库 "ShopEntities" 中维护实体,在我们的 mvc 应用程序中我们正在使用这些实体。
让我们考虑 ShopEntities 中的 class。
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来避免依赖?此外,我们不想创建接口,因为它的范围有限。提前致谢。
如果我理解你的问题,你应该创建中间业务层以将 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
}
}
从表示层抽象出 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 设计的基于消息的方法
我们正在开发一个 Mvc 应用程序,我们希望在其中使用 nInject 来使用依赖注入。目前我们在不同的 class 库 "ShopEntities" 中维护实体,在我们的 mvc 应用程序中我们正在使用这些实体。 让我们考虑 ShopEntities 中的 class。
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来避免依赖?此外,我们不想创建接口,因为它的范围有限。提前致谢。
如果我理解你的问题,你应该创建中间业务层以将 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
}
}
从表示层抽象出 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 设计的基于消息的方法