我正试图了解DI/IoC,NHibernate并让它们在我正在开发的应用程序中很好地协同工作.我对NHibernate和DI/IoC都很陌生,所以不太确定我所做的是否是合理的方式.这是场景:
该应用程序为用户提供了计算特定金融交易的特定值(称为保证金)的能力.每个事务的marging值的计算是通过抽象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{ public Product GetById(string id) { using (ISession session = NHibernateHelper.OpenSession()) return session.Get (id); } } /* Similar repository for Clients */ IRepository clientRepository = new ClientRepository(); IRepository 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填充/生成的产品和客户端依赖关系的Transaction对象?即,给定由用户提供的productId和clientId,是否可能具有如下内容:
// pseudocode Transaction t = IoC.Resolve(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,以便在运行时确定实现者?
非常感谢
马修