我试图让我的头脑围绕 DI/IoC、NHibernate 并让它们为我正在开发的应用程序很好地协同工作。我对 NHibernate 和 DI/IoC 都很陌生,所以不太确定我正在做的事情是否是明智的做法。这是场景:
该应用程序为用户提供了计算特定金融交易的特定价值(称为保证金)的能力。每个交易的保证金值的计算是通过抽象 MarginCalculator 类的具体实现来执行的,而要使用的具体实现取决于特定交易的产品类型(由产品对象的某个字段给出)。具体的计算器类是通过产品类的属性访问的。IE
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
}
}
用户从下拉列表中选择特定的客户端和产品,并将相应的客户端 ID 和产品 ID 传递到存储库,然后使用 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?
非常感谢
马修