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>
Related
All I want to do is (in an app.config) define a singleton 'Int32'. The idea is that it will be a named registration, and used as a parameter in multiple other type definitions - meaning the actual int value itself only needs to be defined once (and reducing manual error).
Something along the lines of the following...
<register type="int" name="MyInt">
<lifetime type="singleton" />
<constructor>
<param name="value" value="23"/>
</constructor>
</register>
Now I realise the Int32 structure doesn't have such a constructor, but what I am requesting seems so simple that I cant believe it cant be done.
Am I missing something obvious?
Cheers!
You should be able to specify a single instance:
<container>
<instance name="FooBar" type="System.Int32" value="123" />
</container>
Which is resolved like so:
int value = container.Resolve<int>("FooBar");
If you would require to construct another type from configuration, it would be like so:
<!-- "SomeType" is a type here, but you can have any mapping here -->
<register type="SomeType">
<constructor>
<!-- "value" is the name of the constructor argument -->
<param name="value" dependencyName="FooBar" />
</constructor>
</register>
Can you change behavior from Dependency injection to reading config file?
Here good example how you can put int value to config file and read it without DI.
Second solution: you can wrap your int value into simple object with singl property and necessary constructor.
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 have registered a generic type in a Unity config file. It works, but ReSharper flags this syntax in red as an INCORRECT_TYPE_PARAMETER_NUMBER error. Is there a way to do this that will keep ReSharper happy, without adding overhead to the config file?
<unity>
<type alias="IList`1" type="System.Collections.Generic.IList`1, mscorlib"/>
^^^^^^^
<type alias="List`1" type="System.Collections.Generic.List`1, mscorlib"/>
^^^^^^
<type alias="string" type="System.String, mscorlib"/>
<type alias="int" type="System.Int32, mscorlib"/>
<register type="IList`1[string]" mapTo="List`1[string], mscorlib"/>
<register type="IList`1[int]" mapTo="List`1[int], mscorlib"/>
</unity>
Have you tried using the full assembly name for mscorlib (including the assembly version, public key token, etc.)?
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>