【发布时间】:2008-12-22 23:37:07
【问题描述】:
我正在努力了解 DI/IoC、NHibernate 并让它们在我正在开发的应用程序中很好地协同工作。我对 NHibernate 和 DI/IoC 都很陌生,所以不太确定我正在做的事情是否是明智的做法。这是场景:
该应用程序为用户提供了计算特定金融交易的特定价值(称为保证金)的能力。每笔交易的保证金值的计算是通过抽象 MarginCalculator 类的具体实现来执行的,而要使用的具体实现取决于特定交易的产品类型(由产品对象的某个字段给出)。具体的计算器类是通过产品类的属性访问的。即
public class Transaction
{
private double _margin;
private Product _product;
private Client _client;
public double Margin { get; }
public Product Product { get; }
public Client Client { get; }
public Transaction(Product p, Client c)
{
_product = p;
_client = c;
}
public void CalculateMargin()
{
_margin = _product.MarginCalculator.CalculateMargin();
}
}
public class Product
{
private string _id;
private string _productType;
... Other fields
public string Id { get; }
public string ProductType { get; }
public MarginCalculator MarginCalculator
{
get { return MarginCalculatorAssembler.Instance.CreateMarginCalculatorFor(this.ProductType); }
}
}
public class MarginCalculatorAssembler
{
public static readonly MarginCalculatorAssembler Instance = new MarginCalculatorAssembler();
private MarginCalculatorAssembler ()
{
}
public MarginCalculator CreateMarginCalculatorFor(string productType)
{
switch (productType)
{
case "A":
return new ConcreteMarginCalculatorA();
case "B":
return new ConcreteMarginCalculatorB();
default:
throw new ArgumentException();
}
}
}
public abstract class MarginCalculator
{
public abstract double CalculateMargin();
}
public class ConcreteMarginCalculatorA : MarginCalculator
{
public override double CalculateMargin
{
// Perform actual calculation
}
}
public class ConcreteMarginCalculatorB : MarginCalculator
{
public override double CalculateMargin
{
// Perform actual calculation
}
}
用户从下拉列表中选择特定的客户端和产品,并将相应的 clientId 和 productId 传递到存储库,然后使用 NHibernate 填充产品和客户端对象,然后再将它们注入事务对象。在我当前的设置中,事务通过构造函数依赖注入(尚未使用 IoC 容器)接收其产品和客户端依赖项,即
public class ProductRepository : IRepository<Product>
{
public Product GetById(string id)
{
using (ISession session = NHibernateHelper.OpenSession())
return session.Get<Product>(id);
}
}
/* Similar repository for Clients */
IRepository<Client> clientRepository = new ClientRepository();
IRepository<Product> productRepository = new ProductRepository();
Client c = clientRepository.GetById(clientId);
Product p = productRepository.GetById(productId);
Transaction t = new Transaction(p, c);
以下是我希望得到的想法:
A. 是否可以通过 Product 域对象访问 MarginCalculator(本质上是一项服务),或者应该按照此处的建议 (http://stackoverflow.com/questions/340461/dependency-injection-with-nhibernate-objects ) 对代码进行重组,以便从域对象中删除服务依赖项,而是创建一个新的 TransactionProcessor 类,该类将抽象 MarginCalculator 作为依赖项(按照此处描述的内容 (http://www.lostechies.com/blogs/jimmy_bogard/archive/2008/03/31/ptom-the-dependency-inversion-principle.aspx) 即强>
public class TransactionProcessor
{
private readonly MarginCalculator _marginCalculator;
public TransactionProcessor(MarginCalculator marginCalculator)
{
_marginCalculator = marginCalculator;
}
public double CalculateMargin(Transaction t)
{
return _marginCalculator.CalculateMargin(Transaction t);
}
}
public abstract class MarginCalculator
{
public abstract double CalculateMargin(Transaction t);
}
B. 是否可以使用 IoC 容器来获取注入 NHibernate 填充/生成的产品和客户端依赖项的事务对象?即给定一个由用户提供的productId和clientId,是否可能有类似的东西:
// pseudocode
Transaction t = IoC.Resolve<Transaction>(productId, clientId);
这样容器解决了Transaction对象的Product和Client依赖,NHibernate被用来根据productId和clientId填充Product和Client,然后将填充的Product和Client注入到Transaction中?
C. 在典型的 DI 场景中,如果类 A 依赖于接口 B,则可能会执行以下操作:
IInterfaceB b = new ClassB();
A a = new A(b);
interface IInterfaceB
{
}
class B : IInterfaceB
{
}
public class A
{
private IIntefaceB _b;
public A(IInterfaceB b)
{
_b = b;
}
}
但是,这实际上是所有 DI 示例的显示方式,它假设 IInterfaceB(在本例中为 B 类)的实现者在设计时是已知的。 有没有办法以在运行时确定实现者的方式使用 DI?
非常感谢
马修
【问题讨论】:
-
您可能希望首先使用“DI”或“IOC”的实际单词,然后使用它们的缩写。我知道 IoC 是什么,但 DI 是什么?
-
依赖注入。概念相同,但名称不同
标签: c# nhibernate dependency-injection inversion-of-control