views:

1051

answers:

6

I'm trying to get my head around DI/IoC, NHibernate and getting them to work nicely together for an application that i'm developing. I'm quite new to both NHibernate and DI/IoC so not quite sure whether what i'm doing is the sensible way to be going about it. This is the scenario:

The application provides users with the ability to calculate a particular value (known as the margin) for a particular financial transaction. The calculation of the marging value for each transaction is carried out by concrete implementations of an abstract MarginCalculator class and the concrete implementation to be used depends on the type of the product for the particular transaction (given by a certain field of the product object). The concrete calculator class is accessed via a property on the product class. i.e.

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
    }
}

Users select a particular client and Product from dropdowns and the corresponding clientId and productId are passed to repositories that then use NHibernate to populate product and client objects before they're injected into the transaction object. In my current setup the Transaction receives its Product and Client dependencies via constructor dependency injection (no IoC container used as yet) i.e.

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);

The following are what i'm hoping to get ideas on:

A. *Is it considered OK to be accessing the MarginCalculator (which is essentially a service) through the Product domain object or should, as suggested here, (http://stackoverflow.com/questions/340461/dependency-injection-with-nhibernate-objects) the code be restructured so as to remove service dependencies from the domain objects and instead create a new TransactionProcessor class that takes the abstract MarginCalculator as a dependency (along the lines of what's described here (http://www.lostechies.com/blogs/jimmy_bogard/archive/2008/03/31/ptom-the-dependency-inversion-principle.aspx) i.e.*

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. Is it possible to use an IoC Container to get a Transaction object with NHibernate populated/generated Product and Client dependencies injected? i.e. Given a productId and clientId, both provided by the user, is it possible to have something like:

// pseudocode
Transaction t = IoC.Resolve<Transaction>(productId, clientId);

such that the container resolves the Product and Client dependencies of the Transaction object, NHibernate is utilised to populate the Product and Client based on the productId and clientId and then the populated Product and Client are injected into the Transaction?

C. In a typical DI scenario, if class A has a dependency on interface B then the following might be done:

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;
    }
}

However, this, which is virtually how all examples of DI are shown, assumes that the implementor of IInterfaceB (in this case Class B) is known at design time. Is there a way to use DI in such a way that the implementor is determined at runtime?

Many thanks

Matthew

A: 

A) If you're going to access the MarginCalculator through the Product domain object, you might as well cut out the middle man and let the DI/IOC container inject the MarginCalculator for you. You can even get rid of the MarginCalculatorAssembler because most DI/IOC containers do most of the boilerplate code of object construction for you.

B and C) It's very possible. In fact, here's how your code would look like if you used LinFu:


// No need to change the Transaction class
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();
    }
}

It would be nice if you could get a DI/IOC to inject the product and client instances into the constructor--but before we do that, you need to register the dependencies with the container. Here's how you do it with LinFu.IOC:

// Next, you'd have to tell LinFu to automatically register your product class:
[Factory(typeof(Product))]
public class ProductFactory : IFactory
{
     object CreateInstance(IServiceRequest request)
     {
          // Grab a copy of the IRepository from the container
          var repository = container.GetService>();

          // Get the id (this assumes that your id is an Int32)
          var id = (int)request.Arguments[0];

          // Return the product itself
          return repository.GetById(id);
     }
}

// Do the same thing with the Client class
// (Note: I did a simple cut and paste to keep things simple--please forgive the duplication)
[Factory(typeof(Client))]
public class ClientFactory : IFactory
{
     object CreateInstance(IServiceRequest request)
     {
          // Grab a copy of the IRepository from the container
          var repository = container.GetService>();

          // Get the id (this assumes that your id is an Int32)
          var id = (int)request.Arguments[0];

          // Return the client itself
          return repository.GetById(id);
     }
}

[Factory(typeof(Transaction))]
public class TransactionFactory : IFactory
{
     object CreateInstance(IServiceRequest request)
     {
        // Note: Argument checking has been removed for brevity
        var container = request.Container;
        var arguments = request.Arguments;
        var productId = (int)arguments[0];
        var clientId = (int)arguments[1];

        // Get the product and the client
        var product = container.GetService(productId);
        var client = container.GetService(clientId);

        // Create the transaction itself
        return new Transaction(product, client);
     }
}

// Make this implementation a singleton
[Implements(typeof(MarginCalculator), LifecycleType.Singleton)]
public class ConcreteMarginCalculatorA : MarginCalculator
{
    public override double CalculateMargin()
    {
        // Perform actual calculation
    }
}

Once you have all that code compiled in one of your assemblies, here's all you need to do to load it into the container:

var container = new ServiceContainer();
container.LoadFrom(AppDomain.CurrentDomain.BaseDIrectory, "YourAssembly.dll");

...Now for the fun part. In order to create your transaction object with the given product and client ID, here's the call you need to make to LinFu.IOC's container:

int productId = 12345;
int clientId = 54321;
string serviceName = null;

// Not pseudocode :)
var transaction = container.GetService(serviceName, productId, clientId);

What makes this interesting is that despite the number of dependencies you might have, LinFu's IOC container will handle 90% of the boilerplate code for you so you don't have to do all this stuff on your own. The best part is that all the implementations above will all be determined/resolved at runtime.

You can practically swap implementations while the program is running, and you can even replace implementations without even recompiling your application. You can find more info here:

http://www.codeproject.com/KB/cs/LinFu_IOC.aspx

HTH :)

plaureano
A: 

Philip,

Thanks for your answer!

B and C:

It's good to know that this kind of functionality is available. I suppose a more important question is whether what i'm trying to do is in fact common practice and whether it's considered good practice. i.e.

  1. Have a container resolve and inject dependencies that have been pre-populated using a persistence framework (e.g. NHibernate) and
  2. Have the container inject concrete implementation of abstract dependencies where the concrete implementation are determined at runtime.

Also, in IoC/DI/NHibernate terminology, does what i'm talking about, have a particular name? Is it, for example, one of the features listed in this comparison or this comparison of .net IoC frameworks? I'd like to read about whether other IoC frameworks (like Castle Windsor) include these functionalities like LinFu does but i don't know whether what i'm describing has a particular name so i don't know what to search for :)

A:

In terms of best practice (i.e. loose coupling, testing etc...), would it be better to remove the service dependency from the domain object or leave it there?

Thanks

Matthew

A: 

According to 'Domain Driven Design', your service would be a 'Domain Service', and it's ok for the rest of your domain to call it directly or depend on it.

If you're going to use Nhibernate, check Spring.net, a very popular DI framework that provides you with DAOS, that already have a session injected on them. It also allows you to use declarative transactions (marking methods with attributes). The docs of the project are very very good.

Last but not least, and don't get me wrong, I think you are using the technology just because (I don't see that you have the NEED for DI), this is cool if you're doing it to learn stuff, but wrong in every other case.

Regards

Pablo Fernandez
Is there ever a NEED case for DI - you can usually do it another way, but isn't the advantage of DI that you decouple the components....
Chris Kimpton
A: 

Pablo,

Thanks for you comments.

Maybe if i elaborate a bit more on one area where i intend to use DI within the project (not only, as you say, to learn about DI but also because i think it's necessary) and then further comments can be made as to whether it's the correct place to be using DI.

As mentioned in the original post the application will make use of a MarginCalculator Service:

public abstract class MarginCalculator
{
    public abstract double CalculateMargin();
}

Note: the service might be an abstract class or an Interface.

Concrete implementations (components in DI terminology?) will be as follows:

public class ConcreteMarginCalculatorA : MarginCalculator
{
    private IDependencyService1 _dependencyService1;
    private IDependencyService2 _dependencyService2;

    // Constructor dependency injection
    public ConcreteMarginCalculatorA(
        IDependencyService1 dependencyService1,
        IDependencyService2 dependencyService2)
    {
        this._dependencyService1 = dependencyService1;
        this._dependencyService2 = dependencyService2;
    }

    public override double CalculateMargin
    {
        // _dependencyService1 and _dependencyService2 
        // required here to perform calcuation.
    }
}

public class ConcreteMarginCalculatorB : MarginCalculator
{
    private IDependencyService3 _dependencyService3;
    private IDependencyService4 _dependencyService4;

    // Constructor dependency injection
    public ConcreteMarginCalculatorB(
        IDependencyService3 dependencyService3,
        IDependencyService4 dependencyService4)
    {
        this._dependencyService3 = dependencyService3;
        this._dependencyService4 = dependencyService4;
    }

    public override double CalculateMargin
    {
        // _dependencyService3 and _dependencyService4 
        // required here to perform calcuation.
    }
}

Aren't the concrete Margin Calculators and their construction a perfect example of where dependency injection should be used and how an IoC container can be used to handle the dependency injection?

I think what i'm trying to do is very similar to how DI/IoC are described in articles such as this one and this one.

Finally, i will then use a factory class, possibly with an inner/child container, in order to dynamically resolve components/implementors (ConcreteMarginCalculatorA, ConcreteMarginCalculatorB etc...) based on a parameter value. To achieve this i'm leaning toward Autofac (http://code.google.com/p/autofac/) which allows for selecting an implementor based on a parameter value (http://code.google.com/p/autofac/wiki/ComponentCreation - Section "Selection of an Implementer based on a Parameter Value"):

public class MarginCalculatorFactory
{
    private readonly IContainer _factoryLevelContainer;

    public MarginCalculatorFactory(IContainer mainContainer)
    {
        _factoryLevelContainer = mainContainer.CreateChildContainer()
        _factoryLevelContainer.RegisterType<MarginCalculator, ConcreteMarginCalculatorA>("ConcMC1");
     _factoryLevelContainer.RegisterType<MarginCalculator, ConcreteMarginCalculatorB>("ConcMC2");
}

public MarginCalculator CreateCalculator(string productType)
{
 return _factoryLevelContainer.Resolve<MarginCalculator>(productType);
}

}

So that in the end i can do:

marginCalculatorFactory.CreateCalculator(productType);

in the client code and get a fully resolved calculator. The calculator could then in turn be dependency injected into the TransactionProcessor Service:

public class TransactionProcessor
{
    private readonly MarginCalculator _marginCalculator;
 private readonly Transaction _transaction;

    public TransactionProcessor(MarginCalculator marginCalculator
        ,Transaction transaction)
    {
            _marginCalculator = marginCalculator;
   _transaction = transaction
    }

    public double CalculateMargin(Transaction t)
    {
            return _marginCalculator.CalculateMargin(transaction);
    }
}

I might be wrong as i'm new to the whole IoC/DI game but it seems to me that this is precisely the kind of scenario that Di/IoC is used for. What do others think?

Thanks

Matthew

Matthew - can you edit your original question to include this?
Chris Kimpton
Mathew - I am probably missing something but in the TransactionProcessor, don't you need the specific marginCalculator for the product and so would just look it up from the IoC container?
Chris Kimpton
+1  A: 

Hi Matthew,

Here's my second take on your questions:

A: In terms of best practice, you can leave the service dependency into the domain object as long as you make sure that you're depending on an interface type. Most (if not all) containers can do that type of injection for you, and it's pretty trivial to mock out each service dependency so you can test every behavior in your concrete classes. I only recommend using abstract classes if you want to refactor out the boilerplate implementation for a particular interface implementation, such as using a base class to do your generic CRUD persistence work.

B and C:

It's good to know that this kind of functionality is available. I suppose a more important question is whether what i'm trying to do is in fact common practice and whether it's considered good practice. i.e.

  1. Have a container resolve and inject dependencies that have been pre-populated >using a persistence framework (e.g. NHibernate) and
  2. Have the container inject concrete implementation of abstract dependencies where the concrete implementation are determined at runtime.

Also, in IoC/DI/NHibernate terminology, does what i'm talking about, have a particular name? Is it, for example, one of the features listed in this comparison or this comparison of .net IoC frameworks? I'd like to read about whether other IoC frameworks (like Castle Windsor) include these functionalities like LinFu does but i don't know whether what i'm describing has a particular name so i don't know what to search for :)

I believe you're actually referring to the comparison posted at this link.

1) AFAIK, it's standard practice to do service injection, but the type of injection that you're referring to would be difficult to do for some of the other frameworks since you have to use domain object IDs to resolve these dependencies at run time, and not all containers support that type of dynamic resolution (aka 'contextual binding'). All things being equal (and assuming that this can be done with the other containers), the only 'best practice' that seems to apply with DI/IoC is that you must use interfaces for your service dependencies.

How these dependencies should be ultimately constructed and resolved should be completely up to you, and in your case, it really doesn't matter if you get these dependencies populated from a persistence framework as long as the container itself is able to eliminate most of the boilerplate resolution code for you.

2) Concrete service injection is standard among DI/IOC frameworks, and most of them can resolve dependencies at runtime; however, these frameworks differ on how and where that injection can be done.

FYI, the two features that you should pay attention to are Constructor Injection and Property Injection. Based on your code examples, I'd say that you'd be more inclined to use constructor injection, so you might want to keep an eye out for how each respective framework does that type of injection for you. HTH :)

plaureano
A: 

Hi Take a look to this post http://fabiomaulo.blogspot.com/2008/11/entities-behavior-injection.html