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>();
Related
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>
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.
How can I "translate" this Unity Fluent API code into XML Design-Time?
container.RegisterType<IRat, Rat>().Configure<Interception()
.SetInterceptorFor<IRat>(new InterfaceInterceptor());
I tried the code here but it seems to be outdated, since I am working with the last version of Unity.
Assuming you want to do interception with an IInterceptionBehavior the configuration would 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">
<assembly name="MyApp"/>
<namespace name="MyApp"/>
<sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Microsoft.Practices.Unity.Interception.Configuration" />
<container>
<extension type="Interception"/>
<register type="MyInterceptor">
<lifetime type="singleton" />
</register>
<register type="IRat" mapTo="Rat">
<interceptor type="InterfaceInterceptor"/>
<interceptionBehavior type="MyInterceptor"/>
</register>
</container>
</unity>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
</configuration>
You need to declare a sectionExtension and then add the Interception extension to the container. Then when registering types supply the interceptor and interceptionBehavior. If using call handlers then you would add the PolicyInjection behavior.
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" />
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>