Unity configuration with inheritance - c#

I have a simple structure of classes, interfaces as follows:
public interface IMessagingClient (interface supporting service bus queue operation)
public class ServiceBusMessagingClient : IMessagingClient (real implementation)
public class MockMessagingClient : IMessagingClient (mock implementation for our unit test)
public class FailoverMessagingClient : IMessagingClient (this implementation internally uses 2 clients and switches roles b/w 2 as and when disaster in a datacenter occur)
{
private IMessagingClient PrimaryClient { get; set; }
private IMessagingClient SecondaryClient { get; set; }
}
We load unity config from web.config/app.config and use it in our product code and test code.
We want following:
For production scenario, PrimaryClient and SecondaryClient should of type ServiceBusMessagingClient
For Test scenario, PrimaryClient and SecondaryClient should of type MockMessagingClient
Our current unity config looks like:
<container name="azure">
<register type="IMessagingClient" mapTo="FailoverMessagingClient"/>
</container>
Do we have to use some interceptors to achieve this? Or by defining a ctor in FailoverMessagingClient and using ctor injection?
Some suggestions would be great!

You can do this using named registrations.
For example, given the following example set up:
namespace ConsoleApplication8
{
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;
public interface IMessagingClient { }
public class ServiceBusMessagingClient : IMessagingClient { }
public class MockMessagingClient : IMessagingClient { }
public class FailoverMessagingClient : IMessagingClient
{
private readonly IMessagingClient primaryClient;
private readonly IMessagingClient secondaryClient;
public FailoverMessagingClient(IMessagingClient primaryClient, IMessagingClient secondaryClient)
{
this.primaryClient = primaryClient;
this.secondaryClient = secondaryClient;
}
}
class Program
{
static void Main(string[] args)
{
var container = new UnityContainer().LoadConfiguration();
var failOverMessagingClient = container.Resolve<IMessagingClient>("Two");
}
}
}
you can hook up the dependencies using the app.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/>
</configSections>
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<alias alias="IMessagingClient" type="ConsoleApplication8.IMessagingClient, ConsoleApplication8" />
<alias alias="ServiceBusMessagingClient" type="ConsoleApplication8.ServiceBusMessagingClient, ConsoleApplication8" />
<alias alias="MockMessagingClient" type="ConsoleApplication8.MockMessagingClient, ConsoleApplication8" />
<alias alias="FailoverMessagingClient" type="ConsoleApplication8.FailoverMessagingClient, ConsoleApplication8" />
<container>
<register type="IMessagingClient" name="One" mapTo="ServiceBusMessagingClient" />
<register type="IMessagingClient" name="Two" mapTo="FailoverMessagingClient">
<constructor>
<param name="primaryClient">
<dependency type="IMessagingClient" name="One" />
</param>
<param name="secondaryClient">
<dependency type="IMessagingClient" name="One" />
</param>
</constructor>
</register>
</container>
</unity>
</configuration>
Changing the line
<register type="IMessagingClient" name="One" mapTo="ServiceBusMessagingClient" />
to
<register type="IMessagingClient" name="One" mapTo="MockMessagingClient" />
will allow you to swap out your implementation of IMessagingClient as appropriate.
Personally, I would rather do this using the fluid syntax
var container = new UnityContainer();
container.RegisterType<IMessagingClient, ServiceBusMessagingClient>("One");
container.RegisterType<IMessagingClient, FailoverMessagingClient>("Two",
new InjectionConstructor(new ResolvedParameter<IMessagingClient>("One"), new ResolvedParameter<IMessagingClient>("One")));
var failOverMessagingClient = container.Resolve<IMessagingClient>("Two");

When using the unity container, you can override an existing registration by registering it again for a different class.
For example:
If you run this code:
container.RegisterType<IMessagingClient, ServiceBusMessagingClient>();
container.RegisterType<IMessagingClient, MockMessagingClient>();
The first registration is overridden and so IMessagingClient is mapped to MockMessagingClient. Its like the first line never executed.
You can use this fact, and in your unit test (in the arrange phase or in the setup method of your test class), simply register the IMessagingClient to the mock implementation like this (after loading the XML configuration):
container.RegisterType<IMessagingClient, MockMessagingClient>();
By the way, you might not want to use DI containers in unit tests. Take a look at this question.

Related

Resolve instance with unity 5.0.0

How do I resolve an instance of a class with the new Unity 5.0.0 Resolve() method?
In Unity 4.0.1 I resolved an instances like the example given below with SettingsContext. But this no longer works.
I am thinking it is a matter of giving a second argument to Resolve, but I am not sure howto.
var _unity = UnityConfig.GetConfiguredContainer();
var _settings = _unity.Resolve<SettingsContext>();
With UnityConfig class being defined as
public class UnityConfig
{
private static Lazy<IUnityContainer> container = new Lazy<IUnityContainer>(() =>
{
var container = new UnityContainer();
RegisterTypes(container);
return container;
});
public static IUnityContainer GetConfiguredContainer()
{
return container.Value;
}
public static void RegisterTypes(IUnityContainer unity)
{
//all the unity.RegisterType calls
}
}
As normal, load the container.
Next load the named section - the default is "unity", but it could be any tag you want in the config file.
Finally, have the section object configure the container.
var c = new UnityContainer();
var section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
section.Configure(c);
var ss = c.Resolve<IStorageSystem>();
For the app|web.config, be sure to reference the updated type definition (see assembly).
<configSections>
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Unity.Configuration"/>
</configSections>
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<container>
<register type="FileBox.IStorageSystem, FileBox" mapTo="FileBox.StorageSystem.Local.LocalFileSystem, FileBox" >
<constructor>
<param name="root">
<value value =""/>
</param>
</constructor>
</register>
</container>

Configuring instances in Unity Container configured in App.Config at runtime

I have a speciifc configuration problem.
<configuration>
<configSections>
<section name="custom" type="ConfigurationSample.CustomConfigurationSection, ConfigurationSample"/>
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/>
</configSections>
<custom>
<customConfigurations>
<configuration id="CAT1">
<name>Tom</name>
<address type="rent">
<area>Misissipi</area>
</address>
<conifugration/>
<configuration id="Mouse1">
<name>Jerry</name>
<address type="own">
<area>Seatle</area>
</address>
<conifugration/>
<customConfigurations>
</custom>
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<alias alias="IAnimal" type="MyApp.IAnimal, MyApp" />
<alias alias="CAT" type="MyApp.CAT, MyApp" />
<alias alias="Mouse" type="MyApp.Mouse, MyApp" />
<container>
<!-- should register CAT instance with name CAT1 at runtime and mapto IAnimal !-->
<!-- should register Mouse with name Mouse1 at runtime and mapto IAnimal !-->
</container>
</unity>
</configuration>
This is my app.config. All I am looking for runtime registering instances in unity container while reading the custom config section since CAT class CAT configuration in its constructor.
My classes:
public interface IAnimal
{
public string Name {get;set}
pubic bool IsLiving();
}
public class Mouse
{
MouseConfig config;
public Mouse(IAnimalConfig config)
{
this.config=config;
}
public string Name {get;set}
pubic bool IsLiving(){
//do something with config
}
}
public class Cat
{
CATConfig config;
public CAT(IAnimalConfig config)
{
this.config=config;
}
public string Name {get;set}
pubic bool IsLiving(){
//do something with config
}
}
I hope you understand where i am leading to. I need to provide config objects as parameter to the derived classes. So based on my customconfig i want to register instances in unity container. So i can work with those instances in my application. since i already know their types and name of those instances i can resolve from container.
Please let me know if i have to add anything more. Thanks

Move Unity code-as-config to XML when having abstract class in between

I've got a working Unity container configured from code. I have to move to xml configuration, but can't make it correctly. I don't know what I am missing - maybe somebody is out there who knows the solution and can help me out!
My solution is about layering my FIX protocol library correctly, to handle different vendor specific messages differently, but to have a good robust backing API for that.
I have two interfaces:
public interface ICriteria
{
bool AreMet(Message message);
}
public interface IConsumer
{
ICriteria Criteria { get; }
void HandleMessage(Message message);
}
There is a default abstract implementation for the consumers:
namespace Fix.MessageHandling
{
public abstract class Consumer : IConsumer
{
private readonly ICriteria criteria;
protected readonly IProcessor Processor;
public ICriteria Criteria
{
get { return this.criteria; }
}
protected Consumer(IProcessor processor, ICriteria criteria)
{
//...
}
}
}
Then I've got some abstract implementations for different FIX message types: each Consumer abstraction has its own Criteria abstraction. (referenced in the constructor as well) e.g.
namespace Fix.MessageHandling.ExecutionReport
{
public abstract class Consumer : MessageHandling.Consumer
{
protected Consumer(IProcessor processor, Criteria criteria)
: base(processor, criteria)
{
// ...
}
}
public abstract class Criteria : ICriteria
{
// ...
}
}
I register the ICriteria instances from code:
container.RegisterType<ICriteria, Vendor.Criteria.Spot>("SpotCriteria");
container.RegisterType<ICriteria, Vendor.Criteria.Swap>("SwapCriteria");
// etc.
After that I register the IConsumer insatnces, which are in this case ExecutionReportConsumer instances, but I am mapping to IConsumer:
container.RegisterType<
IConsumer,
Vendor.Consumer.Spot>("SpotConsumer",
new InjectionConstructor(
container.Resolve<IProcessor>(),
container.Resolve<ICriteria>("SpotCriteria")));
// etc.
When I resolve IConsumer-s, I can get all my registered Consumers from the UnityContainer:
container.ResolveAll<IConsumer>();
This is how I tried to do this with xml after defining all the aliases:
<register type="ICriteria" mapTo="ForwardCriteria" name="ForwardCriteria" />
<register type="IConsumer" mapTo="ForwardConsumer" name="ForwardConsumer">
<constructor>
<param name="processor" dependencyType="IProcessor" />
<param name="criteria" dependencyType="ExecutionReportCriteria" dependencyName="ForwardCriteria" />
</constructor>
</register>
If I use the xml configuration and I call ResolveAll for IConsumers, I've got an exception
Resolution of the dependency failed, type = "Fix.MessageHandling.IConsumer", name = "ForwardConsumer".
Exception occurred while: while resolving.
Exception is: InvalidOperationException - The type Criteria does not have an accessible constructor.
At the time of the exception, the container was:
Resolving Fix.Vendor.Consumer.Forward,ForwardConsumer (mapped from Fix.MessageHandling.IConsumer, ForwardConsumer)
Resolving parameter "criteria" of constructor Fix.Vendor.Consumer.Forward(Fix.MessageHandling.IProcessor processor, Fix.MessageHandling.ExecutionReport.Criteria criteria)
Resolving Fix.MessageHandling.ExecutionReport.Criteria,ForwardCriteria
OK, actually I figured this out by myself and I'm a newbie and don't know what to do - so I answer my own question :]
If I register the criteria interface and my concrete criteria implementations to the correct abstract base class, then it works like a charm!
<register type="ICriteria" />
<register type="ExecutionReportCriteria" mapTo="ForwardCriteria" name="ForwardCriteria" />
<register type="IConsumer" mapTo="ForwardConsumer" name="ForwardConsumer">
<constructor>
<param name="processor" dependencyType="IProcessor" />
<param name="criteria" dependencyName="ForwardCriteria" />
</constructor>
</register>
That is how I managed to get it going:
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<typeAliases>
<typeAlias alias="ICriteria"
type="Fix.MessageHandling.ICriteria, MoveUnityCode-as-configToXML" />
<typeAlias alias="ExecutionReportCriteria"
type="Fix.MessageHandling.ExecutionReport.Criteria, MoveUnityCode-as-configToXML" />
<typeAlias alias="ForwardCriteria"
type="Fix.MessageHandling.ExecutionReport.ForwardCriteria, MoveUnityCode-as-configToXML" />
<typeAlias alias="IConsumer"
type="Fix.MessageHandling.IConsumer, MoveUnityCode-as-configToXML" />
<typeAlias alias="ForwardConsumer"
type="Fix.MessageHandling.ExecutionReport.ForwardConsumer, MoveUnityCode-as-configToXML" />
<typeAlias alias="IProcessor"
type="Fix.MessageHandling.IProcessor, MoveUnityCode-as-configToXML" />
<typeAlias alias="Processor"
type="Fix.MessageHandling.Processor, MoveUnityCode-as-configToXML" />
</typeAliases>
<container>
<register type="ExecutionReportCriteria" mapTo="ForwardCriteria" name="ForwardCriteria" />
<register type="IProcessor" mapTo="Processor" />
<register type="IConsumer" mapTo="ForwardConsumer" name="ForwardConsumer">
<constructor>
<param name="processor" dependencyType="IProcessor" />
<param name="criteria" dependencyType="ExecutionReportCriteria" dependencyName="ForwardCriteria" />
</constructor>
</register>
</container>
</unity>

Unity with interface that extends another interface

I have a class:
public class Foo : IFoo
{
}
and two interfaces:
Public interface IFoo : IBar<SomeType>
{
}
public interface IBar<T>
{
DoSomething(T t);
}
We are using XML Config,the code configuration works fine, but the web.config doesn't.
The error is like:
Resolution of the dependency failed, type = "IFoo", name = "(none)".
Exception occurred while: while resolving.
Exception is: InvalidOperationException - The current type, IBar`1[SomeType], is an interface and cannot be constructed. Are you missing a type mapping?
mlns="http://schemas.microsoft.com/practices/2010/unity">
<alias alias="IFoo"
type="IFoo, Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=e4bf38905880b60b" />
<alias alias="Foo"
type="Foo, Something, Version=1.0.0.0, Culture=neutral, PublicKeyToken=e4bf38905880b60b" />
<container name="SomeName">
<register type="IFoo" mapTo="Foo" />
</container>
</unity>
I believe you're probably using the default instance of the UnityContainer since you didn't mention anything about using a named instance of the container.
<container name="SomeName">
<register type="IFoo" mapTo="Foo" />
</container>
You're registering the mapping to "SomeName" instead of the default container.
Remove
name="SomeName"

How to configure unity container to provide string constructor value?

This is my dad class
public class Dad
{
public string Name
{
get;set;
}
public Dad(string name)
{
Name = name;
}
}
This is my test method
public void TestDad()
{
UnityContainer DadContainer= new UnityContainer();
Dad newdad = DadContainer.Resolve<Dad>();
newdad.Name = "chris";
Assert.AreEqual(newdad.Name,"chris");
}
This is the error I am getting
"InvalidOperationException - the type String cannot be constructed.
You must configure the container to supply this value"
How do I configure my DadContainer for this assertion to pass?
Thank you
You should provide a parameterless constructor:
public class Dad
{
public string Name { get; set; }
public Dad()
{
}
public Dad(string name)
{
Name = name;
}
}
If you can't provide a parameterless constructor, you need to configure the container to provide it, either by directly registering it with the container:
UnityContainer DadContainer = new UnityContainer();
DadContainer.RegisterType<Dad>(
new InjectionConstructor("chris"));
or through the app/web.config file:
<configSections>
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/>
</configSections>
<unity>
<containers>
<container>
<register type="System.String, MyProject">
<constructor>
<param name="name" value="chris" />
</constructor>
</register >
</container>
</containers>
</unity>

Categories