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>
Related
In the app.config, it can look like below and the services and repositories are defined in a different file Unity.config. My question is, is it possible to do below in appsettings.json instead of app.config and Unity.json instead of Unity.config?
app.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="Unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" requirePermission="false" restartOnExternalChanges="true" />
</configSections>
<Unity configSource="Config\Unity.config"/>
<appSettings>
<add key="DateFormat" value="yyyyMMdd"/>
</appSettings>
</configuration>
Unity.config
<Unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<alias alias="IHelpfulRepository" type="Repositories.IHelpfulRepository, Repositories" />
<alias alias="HelpfulRepository" type="Repositories.Implementation.HelpfulRepository, Repositories" />
</Unity>
no it's not possible. there is a work around.
So what I had to do was make my own UnityContainerExtensions class, load an xml file that looks just like an app.config file, get the unity section, and convert that to a UnityConfigurationSection. code below
MyUnityContainerExtensions.cs
public static class MyUnityContainerExtensions
{
public static IUnityContainer LoadXML(this IUnityContainer container, string xmlFilePath = ".\\Config\\Unity.config")
{
XmlDocument doc = new XmlDocument();
doc.Load(xmlFilePath);
var fileMap = new ExeConfigurationFileMap { ExeConfigFilename = xmlFilePath };
Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
UnityConfigurationSection section = (UnityConfigurationSection)configuration.GetSection("unity");
return section.Configure(container, string.Empty);
}
}
Unity.config
<configuration>
<configSections>
<section name="Unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Unity.Configuration" requirePermission="false" restartOnExternalChanges="true" />
</configSections>
<Unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<alias alias="IHelpfulRepository" type="Repositories.IHelpfulRepository, Repositories" />
<alias alias="HelpfulRepository" type="Repositories.Implementation.HelpfulRepository, Repositories" />
</Unity>
...
</configuration>
Then where I'm loading the unity configuration, I just call the new extension method.
IUnityContainer container = new UnityContainer().LoadXML();
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.
I cannot get the IApplication context for my console app
I get an exception with this detail:
The type initializer for 'Spring.Context.Support.ContextRegistry' threw an exception.
With inner exception:
Could not configure Common.Logging from configuration section 'common/logging
There's clearly something basic I've not hooked up, but I'm not sure what.
using Spring.Context;
using Spring.Context.Support;
namespace ConsoleApplication4
{
class Program
{
static void Main(string[] args)
{
IApplicationContext ctx = ContextRegistry.GetContext();
}
}
}
And my app.config looks like this:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="spring">
<section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/>
<section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" />
</sectionGroup>
</configSections>
<spring>
<context>
<resource uri="config://spring/objects"/>
</context>
<objects xmlns="http://www.springframework.net">
<description>An example that demonstrates simple IoC features. </description>
</objects>
</spring>
</configuration>
Spring.Net uses Common Logging as facility for logging, you have to add the logging configuration to your app.config and the proper library to the referenced assemblies.
<configuration>
<configSections>
<sectionGroup name="common">
<section name="logging" type="Common.Logging.ConfigurationSectionHandler, Common.Logging" />
</sectionGroup>
</configSections>
<common>
<logging>
<factoryAdapter type="Common.Logging.Simple.ConsoleOutLoggerFactoryAdapter, Common.Logging">
<arg key="level" value="DEBUG" />
<arg key="showLogName" value="true" />
<arg key="showDataTime" value="true" />
<arg key="dateTimeFormat" value="yyyy/MM/dd HH:mm:ss:fff" />
</factoryAdapter>
</logging>
</common>
</configuration>
http://netcommon.sourceforge.net/docs/1.2.0/reference/html/logging.html#logging-declarative-config
The type initializer for 'Spring.Context.Support.ContextRegistry'
threw an exception
This is valueable information and Spring.net is really good at providing additional information. Whenever Spring.net throws something, be sure to read the InnerException.
WHen I edit my config I get the messages: Could not find schema
information for the attribute #. for # = 'uri', 'context', 'resource'
and 'spring'
This is normal if you didn't install the schemas. You can download the schemas at their site and find additional information in their docs. Please note that this is optional and spring runs without those schemas.
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>();