Unity configuration and nested generic types - c#

I'm new to Unity and have a problem with configuration and nested generic types in a WCF service. Everything has been working fine until I hit the situation where I needed to define a factory which returns instances of types based on a generic interface.
The code looks something like this:
public interface IFactory<T, TResult>
{
TResult CreateInstance(T input);
}
public interface IFilter<T>
{
// throws an exception if an item is to be filtered
void Filter(T itemToFilter);
}
// classes implementing this interface can have multiple filters
public interface IFilterRunner<T>
{
void RunFilters(T itemToFilter);
}
public class FilterRunnerFactory : IFactory<BaseType, IFilterRunner<BaseType>>
{
public IFilterRunner<BaseType> CreateInstance(BaseType input)
{
if (input is SubType)
{
return new SubTypeFilterRunner();
}
throw new InvalidOperationException("Could not create an IFilterRunner for the input.");
}
}
public class Service
{
private readonly IFactory<BaseType, IFilterRunner<BaseType>> _filterRunnerFactory;
public Service(IFactory<BaseType, IFilterRunner<BaseType>> filterRunnerFactory)
{
_filterRunnerFactory = filterRunnerFactory;
}
}
The Unity configuration looks something like this:
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<alias alias="BaseType" type="SomeNamespace.BaseType, SomeAssembly, Version=1.0.0.0, Culture=neutral" />
<alias alias="IFactory" type="SomeNamespace.IFactory`2, SomeAssembly, Version=1.0.0.0, Culture=neutral" />
<alias alias="IFilterRunner" type="SomeNamespace.IFilterRunner`1, SomeAssembly, Version=1.0.0.0, Culture=neutral" />
<alias alias="IService" type="SomeNamespace.IService, SomeAssembly, Version=1.0.0.0, Culture=neutral" />
<containers>
<container>
<register type="IFactory[BaseType,IFilterRunner]" mapTo="SomeNamespace.FilterRunnerFactory, SomeAssembly, Version=1.0.0.0, Culture=neutral"/>
<register type="IService" mapTo="SomeNamespace.Service, SomeAssembly, Version=1.0.0.0, Culture=neutral">
<constructor>
<param name="filterRunnerFactory" />
</constructor>
</register>
</container>
</containers>
</unity>
The configuration seems valid but when the WCF service itself is instantiated I get the following error:
InvalidOperationException - The
current type,
SomeNamespace.IFactory2[SomeNamespace.BaseType,SomeNamespace.IFilterRunner1[SomeNamespace.BaseType]],
is an interface and cannot be
constructed. Are you missing a type
mapping?
I’ve tried all sorts of different options but they all result in invalid configuration. Also, I have had other factory definitions that are defined to return either abstract base types or instances of types based on non-generic interfaces and they have worked fine. The difference is that this factory returns IFilterRunner - a generic interface.
Does anyone have any suggestions? Thanks in advance from a perplexed developer.

I fixed your problem by specifying generic argument for IFilterRunner's alias.
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<alias alias="BaseType" type="SomeNamespace.BaseType, SomeAssembly, Version=1.0.0.0, Culture=neutral" />
<alias alias="IFactory" type="SomeNamespace.IFactory`2, SomeAssembly, Version=1.0.0.0, Culture=neutral" />
<alias alias="IFilterRunner" type="SomeNamespace.IFilterRunner`1[[SomeNamespace.BaseType, SomeAssembly, Version=1.0.0.0, Culture=neutral]], SomeAssembly, Version=1.0.0.0, Culture=neutral" />
<alias alias="IService" type="SomeNamespace.IService, SomeAssembly, Version=1.0.0.0, Culture=neutral" />
<containers>
<container>
<register type="IFactory[BaseType,IFilterRunner]" mapTo="SomeNamespace.FilterRunnerFactory, SomeAssembly, Version=1.0.0.0, Culture=neutral"/>
<register type="IService" mapTo="SomeNamespace.Service, SomeAssembly, Version=1.0.0.0, Culture=neutral">
<constructor>
<param name="filterRunnerFactory" />
</constructor>
</register>
</container>
</containers>
</unity>

Related

Inject complex objects in constructor with Unity XML configuration file

I have the following classes declaration :
Logger Service,FacadeReaderService and BusinessManager. I want to inject Logger Service and FacadeReaderService in BusinessManager using Unity XML configuration.
Logger Service
public class LoggerService : ILoggerService
{
}
FacadeReaderService
public class FacadeReaderService : IFacadeReaderService
{
}
BusinessManager
public class BusinessManager : IBal
{
IFacadeReaderService _facadeReaderService;
ILoggerService _loggerService;
public BusinessManager(IFacadeReaderService facadeReaderService, ILoggerService loggerService)
{
this._facadeReaderService = facadeReaderService;
this._loggerService = loggerService;
}
}
My question is how to inject this complex objects in my BusinessManager class ? Below is what I have done so far in my Unity Config file :
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<typeAliases>
<typeAlias alias="IFacadeReaderService" type="Interfaces.Services.IFacadeReaderService, Interfaces" />
<typeAlias alias="FacadeReaderService" type="Services.FacadeReader.FacadeReaderService, Services" />
<typeAlias alias="ILoggerService" type="Interfaces.Services.ILoggerService, Interfaces" />
<typeAlias alias="LoggerService" type="Services.Log.LoggerService, Services" />
<typeAlias alias="IBal" type="Interfaces.Bal.IBal, Interfaces" />
<typeAlias alias="BusinessManager" type="Bal.BusinessManager, Bal" />
</typeAliases>
<container>
<register type="IFacadeReaderService" mapTo="FacadeReaderService" name="FRS"/>
<register type="ILoggerService" mapTo="LoggerService" name="LS"/>
<register type="IBal" mapTo="BusinessManager" name="BMS">
<constructor>
<param name="facadeReaderService" value="????????" />
<param name="loggerService" value="??????" />
</constructor>
</register>
</container>
</unity>
Well, I found the answer to my question by looking in Microsoft documentation : https://msdn.microsoft.com/en-us/library/ff660914(v=pandp.20).aspx#config_value
I will post the unity config, just in case there is someone who will need it :
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<typeAliases>
<typeAlias alias="IFacadeReaderService" type="Interfaces.Services.IFacadeReaderService, Interfaces" />
<typeAlias alias="FacadeReaderService" type="Services.FacadeReader.FacadeReaderService, Services" />
<typeAlias alias="ILoggerService" type="Interfaces.Services.ILoggerService, Interfaces" />
<typeAlias alias="LoggerService" type="Services.Log.LoggerService, Services" />
<typeAlias alias="IBal" type="Interfaces.Bal.IBal, Interfaces" />
<typeAlias alias="BusinessManager" type="Bal.BusinessManager, Bal" />
</typeAliases>
<container>
<register type="IFacadeReaderService" mapTo="FacadeReaderService" name="FRS"/>
<register type="ILoggerService" mapTo="LoggerService" name="LS"/>
<register type="IBal" mapTo="BusinessManager" name="BMS">
<constructor>
<param name="facadeReaderService">
<dependency name="FRS" />
</param>
<param name="loggerService">
<dependency name="LS" />
</param>
</constructor>
</register>
</container>
</unity>

c# Unity container constructor injection of list<childs>

I would like to know how can we inject List of all child objects of an abstract class to a constructor using xml config.
E.g.:
Class Test
{
public Test(List<A> instances) // So this list should have instance of B & C
{
}
}
abstract Class A
{
}
Class B: A
{
}
Class C: A
{
}
Thanks!!!
You can use following config if you change a type of a Test's constructor argument on IList<A>:
<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">
<namespace name="System.Collections.Generic" />
<namespace name="ConsoleApplication1" />
<assembly name="ConsoleApplication1" />
<container>
<register type="A" mapTo="B" name="B" />
<register type="A" mapTo="C" name="C" />
<register type="IList`1[[A]]" mapTo="A[]" />
</container>
</unity>
</configuration>
So the trick is to map IList<A> interface on A[] - see this question for details.

Using unity xml config to register an interface with nested generics

If I have a class that implements a generic interface it works fine to configure it using the unity xml config.
public interface IReader<T> { }
public class Fund { }
public class FundReader : IReader<Fund> { }
and the unity xml:
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<namespace name="System.ComponentModel" />
<namespace name="TestUnityIssue" />
<assembly name="TestUnityIssue" />
<container>
<register type="IReader[Fund]" mapTo="FundReader" />
</container>
</unity>
And this works just using the following code:
var container = new UnityContainer().LoadConfiguration();
var fundReader = container.Resolve<IReader<Fund>>();
However, in some cases there is a wrapper around the type used in the reader. For example, adding the following two classes:
public class Wrapper<T> { }
public class WrappedFundReader : IReader<Wrapper<Fund>> { }
and if I add the following to the unity config:
<register type="IReader[Wrapper[Fund]]" mapTo="WrappedFundReader" />
and then try to resolve it using:
var wrappedReader = container.Resolve<IReader<Wrapper<Fund>>>();
I get the following exception:
InvalidOperationException - The current type,
TestUnityIssue.IReader`1[TestUnityIssue.Wrapper`1[TestUnityIssue.Fund]],
is an interface and cannot be constructed. Are you missing a type
mapping?
I can get around this by configuring it using code instead of xml:
container.RegisterType<IReader<Wrapper<Fund>>, WrappedFundReader>();
or I can create an interface that goes between and use that instead:
public interface IWrappedReader<T> : IReader<Wrapper<T>> { }
public class WrappedFundReader : IWrappedReader<Fund>
and the config would change to:
<register type="IWrappedReader[Fund]" mapTo="WrappedFundReader" />
It will still give me an instance that I can cast to IReader<Wrapper<Fund>>, but it seems like I should be able to make this work with the unity config.
What am I missing to make this work?
(If also tried creating specific aliases and wasn't able to get that to work either)
Aliasing worked for me...
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<alias alias="WrappedFund" type="TestUnityIssue.Wrapper`1[[TestUnityIssue.Fund, TestUnityIssue, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], TestUnityIssue, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<namespace name="TestUnityIssue" />
<assembly name="TestUnityIssue" />
<container>
<register type="IReader[Fund]" mapTo="FundReader" />
<register type="IReader[WrappedFund]" mapTo="WrappedFundReader" />
</container>
</unity>
these both resolved...
var fundReader = container.Resolve<IReader<Fund>>();
var wrappedReader = container.Resolve<IReader<Wrapper<Fund>>>();
and depending on your situation, you may be able to get away with less than the full AssemblyQualifiedName...
<alias alias="WrappedFund" type="TestUnityIssue.Wrapper`1[[TestUnityIssue.Fund, TestUnityIssue]], TestUnityIssue" />

Unity - Inject different classes for the same interface

I have one interface: IFoo
Two classes implementing that interface: FooOne and FooTwo
And two classes ClassOne and ClassTwo receiving an IFoo parameter in the constructor.
How I configure unity so ClassOne receives a FooOne instance and ClassTwo receives a FooTwo using only one container?
I can't do it at runtime so it must be in the config file.
Have a look at the Unity documentation.
For a more readable config file you should define type aliases for IFoo, FooOne, FooTwo, ClassOne and ClassTwo. Then you need to register the mappings from IFoo to your implementations. You need to set a name for the mappings.
For the consumers of IFoo you need to register an InjectionConstructor.
Your config will look something like this:
<?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="IFoo" type="UnityConfigFile.IFoo, UnityConfigFile" />
<alias alias="FooOne" type="UnityConfigFile.FooOne, UnityConfigFile" />
<alias alias="FooTwo" type="UnityConfigFile.FooTwo, UnityConfigFile" />
<alias alias="ClassOne" type="UnityConfigFile.ClassOne, UnityConfigFile" />
<alias alias="ClassTwo" type="UnityConfigFile.ClassTwo, UnityConfigFile" />
<container>
<register type="IFoo" name="1" mapTo="FooOne" />
<register type="IFoo" name="2" mapTo="FooTwo" />
<register type="ClassOne" mapTo="ClassOne">
<constructor>
<param name="foo">
<dependency type="IFoo" name="1" />
</param>
</constructor>
</register>
<register type="ClassTwo" mapTo="ClassTwo">
<constructor>
<param name="foo">
<dependency type="IFoo" name="2" />
</param>
</constructor>
</register>
</container>
</unity>
</configuration>
That's the corresponding test that shows how it works.
UnityConfigurationSection config =
(UnityConfigurationSection) ConfigurationManager.GetSection("unity");
IUnityContainer container = new UnityContainer();
container.LoadConfiguration(config);
ClassTwo two = container.Resolve<ClassTwo>();
Assert.IsInstanceOfType(two.Foo, typeof(FooTwo));
Update
At runtime you can do it like this
IUnityContainer container = new UnityContainer();
container.RegisterType<IFoo, FooOne>("One");
container.RegisterType<IFoo, FooTwo>("Two");
container.RegisterType<ClassOne>(new InjectionConstructor(
new ResolvedParameter<IFoo>("One")));
container.RegisterType<ClassTwo>(new InjectionConstructor(
new ResolvedParameter<IFoo>("Two")));
You need to give them registration names to do this:
// Create an instance of a service you want to use. Alternatively, this
// may have been created by another process and passed to your application
LoggingService myLoggingService = new LoggingService();
// Register the existing object instance with the container
container.RegisterInstance<IMyService>("Logging", myLoggingService);
// Register a mapping for another service your application will use
container.RegisterType<IMyService, myDataService>("DataService");
// When required, retrieve an instance of these services
IMyService theDataService = container.Resolve<IMyService>("DataService");
IMyService theLoggingService = container.Resolve<IMyService>("Logging");
Taken from Resolving Instances Of Types Using Unity
I setup in my application like this
Installed Nuget Package Unity version 4.0.1
<package id="Unity" version="4.0.1" targetFramework="net452" />
In my App.config
<configSections>
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" />
</configSections>
<unity>
<container>
<register type="MyApp.MainWindow, MyApp">
<lifetime type="singleton" />
</register>
<register name="UnityResolver" type="MyApp.Core.Interface.IResolver, MyApp.Core.Interface" mapTo="Avelyn.Core.Container.UnityResolver, Avelyn.Core" />
<register name="NinjectResolver" type="MyApp.Core.Interface.IResolver, MyApp.Core.Interface" mapTo="Avelyn.Core.Container.NinjectResolver, Avelyn.Core" />
</container>
</unity>
In My App.xaml.cs
var _container = new UnityContainer();
_container.LoadConfiguration();
IResolver _unityResolver = _container.Resolve<IResolver>("UnityResolver");
IResolver _ninject = _container.Resolve<IResolver>("NinjectResolver");
MainWindow _win = _container.Resolve<MainWindow>();

Unity Framework's container type's constructor param's type

Currently I am trying to use a config file to give Unity Framework information that looks like this...
<configuration>
<unity>
<typeAliases>
<typeAlias alias="singleton" type="Microsoft.Practices.Unity.ContainerControlledLifetimeManager, Microsoft.Practices.Unity, Culture=neutral, Version=1.1.0.0, PublicKeyToken=31bf3856ad364e35" />
</typeAliases>
<containers>
<container>
<types>
<type type="Common.ISharedConfiguration, Common, Version=3.1.0.0, Culture=neutral, PublicKeyToken=1111111111111111" mapTo="Common.SharedConfigurationManager, Common, Version=3.1.0.0, Culture=neutral, PublicKeyToken=1111111111111111">
<lifetime type="singleton" />
<typeConfig extensionType="Microsoft.Practices.Unity.Configuration.TypeInjectionElement, Microsoft.Practices.Unity.Configuration, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
<constructor>
<param name="OurEnumChoice" parameterType="MyProjectsEnum" >
<value value="MyProjectsEnum.OurFirstConstant" type="MyProjectsEnum"/>
</param>
</constructor>
</typeConfig>
</type>
</types>
</container>
</containers>
</unity>
</configuration>
If I choose something like System.String and have my concrete class have a construtor of string this config file info for Unity works great. The moment I choose to use an Enum instead of string Unity throws an error like this...
Could not load type MyProjectsEnum from assembly Microsoft.Practices.Unity.Configuration, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf33856ad364e35
I think I need an understanding of what I can pass as an understood type by Unity beyond simple types through this configuration process.
You need to specify fully qualified type name for both 'parameterType' and 'type' attributes. Much the same you did for 'typeAlias' node. By default, Unity looks up its own assembly for unqualified types.

Categories

Resources