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>
Related
Is there any way in UnityContainer check lifetime consistency between type and its dependencies?
For example I want to know (as error or warning, etc) if type with ControllerLifetimeManager has dependency that have TrancientLifetimeManager.
In XML config it look like:
<register type="ITransient" mapTo="TransientType">
<lifetime type="transient" />
</register>
<register type="ISingletone" mapTo="SingletoneType">
<lifetime type="singletone" />
<constructor>
<param name="dependecyParam" dependencyType="ITransient" />
</constructor>
</register>
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.
I have this piece of code in C# using Unity Framework
static void MakeEverythingReady(UnityContainer container)
{
try
{
container.RegisterType<ICar, Maruti>("UseMaruti",
new InjectionConstructor(new ResolvedParameter<MarutiEngine>()));
container.Resolve<ICar>("UseMaruti");
container.RegisterType<IEngine, MarutiEngine>("UseMarutiEngine");
container.Resolve<IEngine>("UseMarutiEngine");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
I have tried to do the same thing using configuration and wrote this ....
<configuration>
<configSections>
<section name="unity"
type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,
Microsoft.Practices.Unity.Configuration" />
</configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<unity>
<typeAliases>
<typeAlias alias="singleton"
type="Microsoft.Practices.Unity.ContainerControlledLifetimeManager,
Microsoft.Practices.Unity" />
</typeAliases>
<containers>
<container name="containerCar">
<type type="UnityCar.IEngine" mapTo="UnityCar.MarutiEngine" name="UseMarutiEngine" />
<type type="UnityCar.ICar" mapTo="UnityCar.Maruti" name="UseMaruti">
<typeConfig extensionType="Microsoft.Practices.Unity.Configuration.TypeInjectionElement,
Microsoft.Practices.Unity.Configuration">
<constructor>
<param name="UseMarutiEngine" parameterType="UnityCar.IEngine">
<dependency/>>
</param>
</constructor>
</typeConfig>
</type>
</container>
</containers>
</unity>
</configuration>
Trying to load this configuration file using following piece of code
UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
section.Configure(container, "containerCar");
Here we have two assemblies UnityExample is a console and UnityCar is a dll which having all interfaces and concrete implementations. This config file is app.config of UnityExample.
It is throwing configuration exception --
Unrecognized element 'typeConfig'
Any clue?
I've seen this problem before. Unfortunately, I cannot manage to solve it as I expected.
For me, the solution was removing the typeConfig element from the config.
So I guess, if you modify your app.config to this, It should work:
<type type="UnityCar.ICar" mapTo="UnityCar.Maruti" name="UseMaruti">
<constructor>
<param name="UseMarutiEngine" parameterType="UnityCar.IEngine">
<dependency/>>
</param>
</constructor>
</type>
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>();
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>