Locate different generic services in one non generic Locator - c#

I have various Services that implement
public interface IReceiver<PayLoad>
{
string Name {get;}
Task SendObjectContainerAsync(ObjectContainer<PayLoad> m);
Task<ObjectContainer<PayLoad>> GetSnapshot();
}
For Example
public class Printer : IReceiver<TextDocument>
or
public class TextDocumentService : IReceiver<Letter>
Now I want to collect all instances of each IReceiver in one Controller, I could
public class Broker<Payload>
{
List<IReceiver<Payload>> receivers;
}
and initialize an Instance for each type of IReceiver and then DI it into the IReceivers to enable them to register and get the Instances from other places.
Is this a good way to handle different Services? I think it gets kind of messy with many Brokers and I would rather have something like
static void register<Payload>(IReceiver<Payload> RegisterMe)
and
static List<IReceiver<Payload>> getReceivers<PayLoad>()
But im not able to implement this Locator because I dont know how to administrate different generic Lists in one non generic class
Any Suggestions?

Using a Dependency Injection framework you should be able to configure which receivers you want to particulary inject into specific Broker<PayLoad> instances.
In the other hand, you should practice constructor injection:
public class Broker<Payload>
{
public Broker(IList<IReceiver<PayLoad>> receivers)
{
Receivers = receivers;
}
public IList<IReceiver<PayLoad>> { get; }
}
Now, the next issue is that you want a broker to handle more than a receiver type. So the easiest way will be a small refactor on your IReceiver<PayLoad> interface:
// No more PayLoad generic type parameter! Let's move it to
// the methods
public interface IReceiver
{
string Name { get; }
Task SendObjectContainerAsync<TPayLoad>(ObjectContainer<TPayLoad> m);
Task<ObjectContainer<TPayLoad>> GetSnapshot<TPayLoad>();
}
Finally, your brokers will look as follows:
public class Broker
{
public Broker(IList<IReceiver> receivers)
{
Receivers = receivers;
}
public IList<IReceiver> { get; }
}
About the Locator thing
Are you going to implement a static service locator? Don't do this, it's considered an anti-pattern, because you're going to couple your components to how they receive their dependencies while you should avoid this.
Components should remain agnostic on how they get their dependencies, because this is a reponsibility of a higher layer, usually the IoC/DI container.
Also, it makes your code more test-friendly, because you can test your components without integrating the IoC/DI container, because you just expect constructor arguments.

Related

Injecting parents into composite constructors with Unity C#

I am trying to get IoC working with Unity in C# with the idea of a passing a wrapper/composite class into the children.
The top level class that composes multiple classes provides some common functionality that the composed classes require access to.
To illustrate:
// The top composite class
public class Context : IContext {
public ISomething SomethingProcessor { get; }
public IAnother AnotherProcessor { get; }
public Context(ISomething something, IAnother another) {
this.SomethingProcessor = something;
this.AnotherProcessor = processor;
}
// A function that individual classes need access to, which itself calls one of the children.
public string GetCommonData() {
return this.AnotherProcessor.GetMyData();
}
}
public class Something : ISomething {
private _wrapper;
public Something(IContext context) {
this._wrapper = context;
}
// This class has no knowledge of IAnother, and requests data from the master/top class, which knows where to look for whatever.
public void Do() {
Console.WriteLine(_wrapper.GetCommonData());
}
}
public class Another : IAnother {
public string GetMyData() {
return "Foo";
}
}
If you didn't use IoC, it's easy, as the constructor for the Context class becomes:
public Context() {
this.SomethingProcessor = new Processor(this);
this.AnotherProcessor = new Another();
}
But when you're using IoC, the idea of "this" doesn't exist yet because it is yet to be constructed by the injector. Instead what you have a is a circular dependency.
container.RegisterType<ISomething, Something>();
container.RegisterType<IAnother, Another>();
container.RegisterType<IContext, Context>();
var cxt = container.Resolve<IContext>(); // StackOverflowException
The above example has been greatly simplified to illustrate the concept. I'm struggling to find the "best practice" way of dealing with this kind of structure to enable IOC.
Factory pattern is a way construct an object based on other dependencies or logical choices.
Factory Method: "Define an interface for creating an object, but let
the classes which implement the interface decide which class to
instantiate. The Factory method lets a class defer instantiation to
subclasses" (c) GoF.
Lots of construction.. hence the name Factory Pattern
A crude code sample that could be used with DI
public class ContextFactory : IContextFactory {
_anotherProcessor = anotherProcessor;
public ContextFactory(IAnotherProcessor anotherProcessor) {
//you can leverage DI here to get dependancies
}
public IContext Create(){
Context factoryCreatedContext = new Context();
factoryCreatedContext.SomethingProcessor = new SomethingProcessor(factoryCreatedContext )
factoryCreatedContext.AnotherProcessor = _anotherProcessor;
//You can even decide here to use other implementation based on some dependencies. Useful for things like feature flags.. etc.
return context;
}
}
You can get away with this, maybe? - but there is still the cyclic reference issue here and I would never commit this kind of code.
The problem here you need to concentrate on Inversion Of Control of that GetCommonData
Your SomethingProcessor should not rely on methods in another class. This is where In Inheritance could be used but Inheritance can become very complicated very quickly.
The best way forward is to Identify the ONE thing that is needed by both or many other places and break that out into a new Dependency. That is how you Invert Control.
TIP:
Don't overdo Interfaces- Use Interfaces where you think you will be working with Polymorphism, such as a collection of different objects that must promise you they have implemented a specific method/property. Otherwise you are over using Interfaces and increasing complexity. DI doesn't have to use Interfaces it can be a concrete implementation. Interfaces on Repositories are a good use since you can switch Databases out easily but Interfaces a factory like this is not really needed.
I don't know the name of this pattern, or even if it is a bad or good practice, but you can solve your problem of "double-binding" by creating a method to bind the "IContext", instead of doing it in the constructor.
For instance,
1) ISomething has a void BindContext(IContext context) method
2) You implement it as such :
class Something : ISomething
{
IContext _wrapper;
// ... nothing in constructor
public void BindContext(IContext context)
{
_wrapper = context;
}
}
3) Remove the IContext dependency injection in Something constructor.
And you call it from the context constructor :
public Context(ISomething something, IAnother another) {
this.SomethingProcessor = something;
this.SomethingProcessor.BindContext(this);
// same for IAnother
}
And you do the same for IAnother. You could even extract some common interface "IBindContext" to make things a beat more "DRY" (Don't Repeat yourself) and make IAnother and ISomething inherit from it.
Not tested, and again : not sure it's the best way to do such dependency design. I'll be glad if there is another answer which gives a state-of-the-art insight about this.

Isolating a dependency for an instance (and that instances dependencies) when instance created through a Factory

EDIT: I've cleaned this question up significantly after solving my problem, including changing the title.
I have a MessageChannel interface which defines (unsurprisingly) a channel that my classes can use to push messages to the end user.
Normally this MessageChannel is a Singleton and is bound to a ViewModel that implements the MessageChannel interface. Essentially, there is a single location at the top of my application where messages to the user will be shown. So far its worked pretty well.
This MessageChannel is used in a lot of places, one of which is in some operation classes that I have setup.
I now have a need for a LOCAL MessageChannel, such messages being posted in some reduced scope get posted to that local MessageChannel and not the global one.
What this means is that I need to be able to create instances of a ViewModel (through a Factory), such that that particular instance has its own MessageChannel instance AND that MessageChannel instance is shared for all dependencies injected into that ViewModel (and their dependencies and so on).
Some classes to illustrate. I have simplified things somewhat, my messages are more than just strings:
using Ninject;
using Ninject.Extensions.Factory;
public interface MessageChannel
{
void PostMessage(string message);
}
public class MessageChannelViewModel : MessageChannel
{
public string Message { get; set; }
public void PostMessage(string message)
{
Message = message;
}
}
public interface Operation
{
void Do();
}
public interface OperationFactory
{
Operation Create();
}
public class DefaultOperation : Operation
{
public DefaultOperation(MessageChannel userMessages)
{
_UserMessages = userMessages;
}
private readonly MessageChannel _UserMessages;
public void Do()
{
// Do something.
_UserMessages.PostMessage("Success!");
}
}
public interface IsolatedViewModel
{
MessageChannelViewModel LocalMessages { get; }
}
public interface IsolatedViewModelFactory
{
IsolatedViewModel Create();
}
public class DefaultIsolatedViewModel : IsolatedViewModel
{
public IsolatedViewModel(MessageChannelViewModel localMessages, OperationFactory opFactory)
{
_OpFactory = opFactory;
LocalMessages = localMessages;
}
private readonly OperationFactory _OpFactory;
public MessageChannelViewModel LocalMessages { get; private set; }
}
public class Module : NinjectModule
{
public override void Load()
{
Bind<MessageChannel, MessageChannelViewModel>().To<MessageChannelViewModel>().InSingletonScope();
Bind<Operation>().To<DefaultOperation>();
Bind<OperationFactory>().ToFactory();
Bind<IsolatedViewModel>().To<DefaultIsolatedViewModel>();
Bind<IsolatedViewModelFactory>().ToFactory();
// Something to make it so the IsolatedViewModel DOESNT get the Singleton
// instance of the MessageChannelViewModel, and instead gets once of its own
// AND so the Operations created by the OperationFactory injected into the
// IsolatedViewModel get the SAME MessageChannel, so messages being posted
// from any place in the IsolatedViewModel's dependencies are shown only\
// locally.
}
}
I tried the NamedScope extension but I couldn't get it do what I wanted it to do.
I think you can try to use The Ninject Context Preservation Extension which adds support for recording (and making available to Contextual Binding rules) the context pertaining to factories that call the Kernel to Resolve Requests.
This enables you to add contextual conditions to your Bindings.
I ended up using a combination of Ninject.Extensions.ContextPreservation and Ninject.Extensions.NamedScope to accomplish what I wanted.
The completed example module looks like this:
public class Module : NinjectModule
{
public override void Load()
{
Bind<MessageChannel, MessageChannelViewModel>().To<MessageChannelViewModel>().InSingletonScope();
Bind<Operation>().To<DefaultOperation>();
Bind<OperationFactory>().ToFactory();
var uniqueName = "UNIQUE";
Bind<IsolatedViewModel>()
.To<DefaultIsolatedViewModel>()
.Named(uniqueName)
.DefinesNamedScope(uniqueName);
Bind<MessageChannel, MessageChannelViewModel>().To<MessageChannelViewModel>()
.WhenAnyAncestorNamed(uniqueName)
.InNamedScope(uniqueName);
Bind<IsolatedViewModelFactory>().ToFactory();
}
}
Theres two parts to it.
You need the ContextPreservation extension to choose the correct binding based on the context available at the time that you resolve the object instance. In this case I used a name as context, meaning that my special MessageChannel binding will be used when resolving the MessageChannel dependency for any dependencies required under the IsolatedViewModel.
I needed the NamedScope extension to ensure that only 1 instance of the MessageChannel was created under each IsolatedViewModel instance (i.e. the instance was shared for that IsolatedViewModel and all its dependencies).
Some other things to be aware of:
If you are using any ToMethod bindings and you use the Kernel inside the method, you'll need to make sure you use a ContextPreservingGet or you'll lose your context and the correct binding wont be selected.
You'll have to look very closely at your bindings and double check any Singleton bindings because if any of the dependencies of your isolated class are bound in Singleton scope, and they have dependencies on the MessageChannel (for example) its not going to work like you want it to. I had to remove a couple of Singleton scoped bindings as a result of this (for the better probably).

How do I wire an IoC Container to pass a value to a factory method to resolve?

Background / Goal
We have several "client sites" on our web app that users can switch between
We do a lot of wiring up of objects based on factories that take in the client site ID and create an instance
I would like to inject these dependencies into the classes instead
I also want to make sure I can pass in my own implementations to the constructor for the purposes of unit testing.
We have initially elected to use StructureMap 3.x to do so, but are open to alternatives if they can help us solve this scenario gracefully.
Question
In instances where I require a different dependency based on a client site ID that I'll only get at run-time, what is the appropriate way to set up an IoC container and the appropriate way to request the object from it in order to make it as painless as possible?
Am I thinking about this wrong and unintentionally creating some sort of anti-pattern?
Example Code
Normally we're doing something like the following coming in:
public class MyService
{ DependentObject _dependentObject;
public MyService(int clientSiteID)
{
// ...
_dependentObject = new dependentObjectFactory(clientSiteID).GetDependentObject();
}
public void DoAThing()
{
//...
_dependentObject.DoSomething();
}
}
What I'd like to do:
public class MyService
{ DependentObject _dependentObject;
public MyService(int clientSiteID)
{
// ...
_dependentObject = MyTypeResolver.GetWIthClientContext<IDependentObject>(clientSiteID);
}
public MyService(int clientSiteID, IDependentObject dependentObject)
{
// ...
_dependentObject = dependentObject;
}
public void DoAThing()
{
//...
_dependentObject.DoSomething();
}
}
I would set up the IoC container in such a way that I can use my MyTypeResolver to pass in the clientSiteID, and have the container call my DependentObjectFactory and return the correct object result.
I'm new to IoC containers, and while I'm trying to plow through the literature, I have the feeling it may be easier than I'm making it so I'm asking here.
Probably the simplest way to do this is to use an Abstract Factory. Most IOC frameworks can auto-create them for you, but here's how you can do it manually (I always prefer to do it manually first so I know it works, and then you can check out how the framework can help you automagic it)
Now one thing to mention - I would recommend a slight readjustment of how the final solution works, but I'll go into that once I have shown how it can currently work. Example below assumes Ninject and please excuse any typos, etc.
First create an interface for your dependency
public interface IDependentObject
{
void DoSomething();
}
Then declare empty marker interfaces for each specific implementation of IDependentObject
public interface INormalDependentObject:IDependentObject{};
public interface ISpecialDependentObject:IDependentObject{}
and implement them:
public class NormalDependentObject:INormalDependentObject
{
readonly int _clientID;
public DependentObject(int clientID)
{
_clientID=clientID;
}
public void DoSomething(){//do something}
}
public class DependentObject:ISpecialDependentObject
{
readonly int _clientID;
public DependentObject(int clientID)
{
_clientID=clientID;
}
public void DoSomething(){//do something really special}
}
and of course as you mentioned you may have many more implementations of IDependentObject.
There may be a more elegant way of allowing your IOC framework to resolve at runtime without having to declare the marker interfaces; but for now I find it useful to use them as it makes the binding declarations easy to read :)
Next, declare an interface and implementation of an IDependentObjectFactory:
public interface IDependentObjectFactory
{
IDependentObject GetDependenObject(int clientID);
}
public class DependentObjectFactory: IDependentObjectFactory
{
readonly _kernel kernel;
public DependentObjectFactory(IKernel kernel)
{
_kernel=kernel;
}
public IDependentObject GetDependenObject(int clientID)
{
//use whatever logic here to decide what specific IDependentObject you need to use.
if (clientID==100)
{
return _kernel.Get<ISpecialDependantObject>(
new ConstructorArgument("clientID", clientID));
}
else
{
return _kernel.Get<INormalDependentObject>(
new ConstructorArgument("clientID", clientID));
}
}
}
Wire these up in your Composition Root:
_kernel.Bind<INormalDependentObject>().To<NormalDependentObject>();
_kernel.Bind<ISpecialDependentObject>().To<SpecialDependentObject>();
_kernel.Bind<IDependentObjectFactory>().To<DependentObjectFactory>();
and finally inject your factory into the service class:
public class MyService
{
IDependentObject _dependentObject;
readonly IDependentObjectFactory _factory;
//in general, when using DI, you should only have a single constructor on your injectable classes. Otherwise, you are at the mercy of the framework as to which signature it will pick if there is ever any ambiguity; most all of the common frameworks will make different decisions!
public MyService(IDependentObjectFactory factory)
{
_factory=factory;
}
public void DoAThing(int clientID)
{
var dependent _factory.GetDependentObject(clientID);
dependent.DoSomething();
}
}
Suggested changes
One immediate change from your structure above is that I have left clientID out of the service constructor and moved it to a method argument of DoAThing; this is because it makes a bit more sense to me that the Service itself would be stateless; of course depending on your scenario, you may want to not do that.
I mentioned that I had a slight adjustment to suggest , and it's this; the solution above depends (no pun!) on implementations of IDependentObject having a constructor with this signature:
public SomeDependency(int clientID)
If they don't have that signature then the factory won't work; personally I don't like my DI to have to know anything about constructor params because it takes you out of purely dealing with interfaces and forcing you to implement specific ctor signatures on your concrete classes.
It also means that you can't reliably make your IDependentObjects be part of the whole DI process (i.e whereby they themselves have dependency graphs that you want the framework to resolve) because of the forced ctor signature.
For that reason I'd recommend that IDependentObject.DoSomething() itself be changed to DoSomething(int clientID) so that you can elide the new ConstructorArgument part of the factory code; this means that your IDependentObject s can now all have totally different ctor signatures, meaning they can have different dependencies if needs be. Of course this is just my opinion, and you will know what works best in your specific scenario.
Hope that helps.

Constructor injection with non-dependency parameters

I have an interface ITradingApi like so:
public interface ITradingApi
{
IOrder CreateOrder(...);
IEnumerable<Symbol> GetAllSymbols();
// ...
}
This is meant to be a facade for the different APIs of the vendors of trading software.
My view model has a dependency on this trading API in its constructor:
public class MainViewModel
{
public MainViewModel(ITradingApi tradingApi) { /* ... */ }
// ...
}
I use Ninject as an IoC container, so I will create an instance of my view model like this:
var vm = kernel.Get<MainViewModel>();
Now, my problem:
The implementation of ITradingApi might need additional parameters to work.
Example:
One vendors API uses TCP/IP internally, so I need a hostname and a port.
Another vendor uses a COM object. Here I don't need any info.
A third vendor needs username and password of the account.
In the spirit of not allowing incomplete objects, I added these as parameters to the constructors of the concrete implementations.
Now, I am not sure, how this would work. Clearly, these additional parameters do not belong into the interface, because they are specific to each implementation.
On the other hand, these additional parameters need to be entered by the end-user and then passed to the implementation of ITradingApi, meaning that the user of ITradingApi needs intimate knowledge about the concrete implementation.
How to solve this dilemma?
UPDATE:
One approach could be to create an ITradingApiProvider that exposes a list of required parameters. The View could automatically create an input form for these parameters that is databound to the parameters in ITradingApiProvider. Now, when an ITradingApi instance is requested from the provider, it can make use of these parameters to create an instance of the concrete implementation. Clearly the implementation of ITradingApiProvider and ITradingApi are tightly coupled, but I think that is not a problem as long as each implementation of ITradingApi comes with a corresponding implementation of ITradingApiProvider.
Based on the information so far put forth here, I'd like to point out one or two things:
First of all, whether or not the concrete configuration values are supplied at composition time or truly first available at runtime as user input makes a huge difference. As long as they can be resolved at composition time things are easy because you can simply read the values from the environment and supply them to the appropriate constructors. So, for the rest of this answer I'm going to assume that things are much harder and you actually need to get those values from the user at runtime.
Instead of attempting to come up with a general-purpose configuration API I'd much rather model what's actually going on. In this case it sounds to me like we're collecting configuration values from the user, so why not model this explicitly?
Product Trader
Define an interface like this:
public interface ITradingApiTrader
{
ITradingApi Create(Type apiType);
}
Here, it's assumed that apiType can cast to ITradingApi, but this can't be enforced by the compiler. (The reason I'm calling this a 'Trader' is because this is a variation of the Product Trader pattern (PLoPD 3).)
How is this different than before?
Well, you can implement the Create method by showing a user interface for each type of ITradingApi. Each concrete user interface gathers the values required for its own concrete ITradingApi implementation and subsequently returns a correctly configured instance.
If you know the concrete types at compile time, other variations include these:
public interface ITradingApiTrader
{
ITradingApi CreateMT4TradingApi();
ITradingApi CreateFooTradingApi();
ITradingApi CreateBarTradingApi();
// etc.
}
Perhaps you can also do this (although I haven't tried to compile this):
public interface ITradingApiTrader
{
ITradingApi Create<T>() where T : ITradingApi;
}
Note also that you don't need to define the first ITradingApiTrader's Create method based on a Type - any identifier (such as an enum or string) might do instead.
Visitor
If the set of ITradingApi is (finite and) known at design time, the Visitor design pattern might also offer an alternative.
If you use a Visitor, you can make the Visit method show an appropriate user interface and then subsequently use the values collected from the user interface to create the appropriate ITradingApi instance.
Basically this is just a variation on the previous 'solution' where the Product Trader is implemented as a Visitor.
Is this what your after?
ninjectKernel.Get<MainViewModel>().WithConstructorArgument("tradingApi",
kernel.Get<ITaxCalculator>() .WithConstructorArgument("additionalParameter","someValue")));
Ok my two cents, I am not sure of anything you know. It is just to help and try...
We give a visitor to your api as construction of the interface:
public interface ITradingApi
{
Object CreateOrder();
IEnumerable<Object> GetAllSymbols();
}
public class TradingApi : ITradingApi
{
IvisitorAPI _VisitorAPI;
public TradingApi(IvisitorAPI visitorAPI)
{
_VisitorAPI = visitorAPI;
}
public Object CreateOrder()
{
var Order = new Object();
//bla bla bla
//here code relative to different visitor
_VisitorAPI.SaveOrder(Order);
return Order;
}
}
It is your visitor that knows how to handle some of the action, because depending on the visitor he will use your api in different ways to achieve the same action ( here SaveOrder).
public interface IvisitorAPI
{
bool SaveOrder(Object order);
}
public class visitorApiIP : IvisitorAPI
{
public string HostName { get; set; }
public int Port { get; set; }
public visitorApiIP(string hostname, int port)
{
HostName = hostname;
Port = port;
}
public bool SaveOrder(Object order)
{
//save the order using hostname and ip
//...
//....
return true;
}
}
Only the visitor has a knowledge of what he needs to achieve his version of the action.
Therefore it is not the APi that needs additionnal parameters, we are pushing the logic away in the visitor class.
This visitor class might be created only when ewe know who is the visitor therefore, surely at runtime
Hope it might give you some perspective. I do not know if the whole theory can be applied your exact situation.
My best anyway ;)
The solution is to use the approach as outlined in the update part of my question. ITradingApiProvider takes the role of an abstract factory and thus should be renamed to ITradingApiFactory. It would expose a list of needed parameters whose values can be set. This list in turn can be used by the View to automatically present the user with an input form to enter a value for each parameter, because only the user knows the values of for the parameters.
The call to Create would then use these parameters:
public interface ITradingApiFactory
{
ITradingApi Create();
IEnumerable<Parameter> Parameters { get; }
}
public class Parameter
{
public Parameter(Type type, string name, string description)
{ Type = type; Name = name; Description = description; }
public Type Type { get; private set; }
public string Name { get; private set; }
public string Description { get; private set; }
public object Value { get; set; }
}
public class MT4TradingApiFactory : ITradingApiFactory
{
Dictionary<string, Parameter> _parameters;
public MT4TradingApiFactory()
{ /* init _parameters */ }
public ITradingApi Create()
{
return new MT4TradingApi(_parameters["hostname"].ToString(),
(int)_parameters["port"]);
}
IEnumerable<Parameter> Parameters { get { return _parameters.Values; } }
}
More info can be found in this answer.
This can be advanced further to make it easier to use, by giving each Factory implementation the parameters as properties and change the Parameter class to work directly on these properties using expression trees. If someone is interested in this advanced factory design, please leave a comment.
I think there is nothing wrong with your provider approach. You have two concerns here:
An operational one: your ITradingAPI which defines a contract for operations you can perform.
A meta-data one: something which describes properties of an actual implementation (meta data might not be quiet right but can't think of a better name for it)
Now apparently you need something which can make the connection between the two and that is your ITradingAPIProvider. Seems reasonable straight forward and has good chance of that you will still understand your code when coming back to it after a year ot two ;)
How about trying something similar to the strategy pattern? Create a new interface called IConnectStrategy:
interface IConnectStrategy
{
void Connect();
}
Add the connectstrategy as an argument to the method void CreateOrder(IConnectStrategy connectStrategy) in ITradingApi and let each vendor create/specify their own method for connecting. E.g. for one vendor create:
public class TCPConnectStrategy : IConnectStrategy
{
public TCPConnectStrategy(string hostName, int port)
{
/* ... */
}
public void Connect()
{
/* ... tcp connect ... */
}
}
(Connect might not be the best name or even what you are actually doing, but please apply it to whatever works for your project.)
Edit after comments:
Create a strategy that only have contracts for each method that have vendor-specific parameters. Then add a method void SetVendorStrategy(IVendorStrategy vendorStrategy) (or a property) to the ITradingAPI-interface. Each implementation of the strategy has their own constructor with their own parameters, and each method (that require vendor specific parameters) in each implementation of the ITradingAPI-interface simply calls vendorStrategy.DoSomethingWithVendorSpecificData().

DI/IoC, NHibernate and help in getting them to work together

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) 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 :)
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.
Have a container resolve and inject dependencies that have been pre-populated >using a persistence framework (e.g. NHibernate) and
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 :)
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.
Have a container resolve and inject dependencies that have been pre-populated using a persistence framework (e.g. NHibernate) and
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
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,
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
Take a look to this post
http://fabiomaulo.blogspot.com/2008/11/entities-behavior-injection.html

Categories

Resources