How to Inject Log4Net ILog implementations using Unity 2.0 - c#

Ultimately this has to do with setting up log4Net but generically the problem is not logging specific.
Generically what I am trying to figure out is how to do, in Microsoft Unity 2.0, something equivalent to what one gets with the Castle.Facilities.Logging.LoggingFacility. Namely the ability to declare a dependency on a logger and have the logger initialized with the Type of the object into which it is being injected.
In the spirit of a test is worth a thousand words, here is what I need:
class Logger_IOC_Tests
{
//[Test]
public void Logger_should_be_initialized_with_the_type_of_the_object_that_is_using_it()
{
var container = new UnityContainer();
/* Configuration Magic probably involiving registering either
* a custom IDependencyResolverPolicy or BuilderStrategy
* goes here...
*/
container.RegisterType<LoggerUser>(new ContainerControlledLifetimeManager());
var user = container.Resolve<LoggerUser>();
Assert.True(user.Logger.GetUserType() == user.GetType());
}
}
interface ILogger
{
Type GetUserType();
}
class Logger : ILogger
{
private readonly Type _type;
public Logger(Type type)
{
_type = type;
}
public Type GetUserType()
{
return _type;
}
}
class LoggerUser
{
public readonly ILogger Logger;
public LoggerUser(ILogger logger)
{
Logger = logger;
}
}

I don't know if this what you are looking for, but I saw it a few months ago and was reminded of it when I saw your question. I have not used Unity, so I can't really compare what you have posted with what is at the link. Hopefully it will be useful to you:
http://davidkeaveny.blogspot.com/2011/03/unity-and-log4net.html

I've been trying to achieve the same result of being able to insert correctly configured ILog instances into a dependency using constructor injection with Unity.
In the end, I wrote my own "log4net" unity extension to do exactly this (in part inspired by a blog post that another answerer, Kenneth Baltrinic, wrote).
This allows you to register the extension once with Unity:
var container = new UnityContainer();
container.AddNewExtension<Log4NetExtension>();
and then have the correct ILog logger instance passed in:
public class MyClass
{
private readonly ILog logger;
public MyClass(ILog logger)
{
this.logger = logger;
}
}
The extension can be found here:
https://github.com/roblevine/UnityLoggingExtensions
More info here: http://blog.roblevine.co.uk/net/using-log4net-with-unity/
EDIT this is now available as a NuGet package

After hours of digging around in the Unity source code, I came up with the following solution. However, I would prefer to find a way to set the appropriate dependency resolver based on the type being resolved rather than overriding the default constructor selector policy. For one, because I previously overrode the default constructor selector for other purposes. For another, this solution only handles dependencies that are injected via constructor. For full coverage one would have to override the default property and method selectors as well I presume. For myself, I only need constructors.
class Logger_IOC_Tests
{
[Test]
public void Logger_should_be_initialized_with_the_type_of_the_object_that_is_using_it()
{
var container = new UnityContainer();
container.AddNewExtension<LoggingExtension>();
container.RegisterType<LoggerUser>(new ContainerControlledLifetimeManager());
var user = container.Resolve<LoggerUser>();
Assert.True(user.Logger.GetUserType() == user.GetType());
}
}
class LoggingExtension : UnityContainerExtension
{
protected override void Initialize()
{
Context.Policies.SetDefault(typeof(IConstructorSelectorPolicy), new LoggingConstructorSelectorPolicy());
}
}
public class LoggingConstructorSelectorPolicy : DefaultUnityConstructorSelectorPolicy
{
protected override IDependencyResolverPolicy CreateResolver(ParameterInfo parameter)
{
return parameter.ParameterType == typeof(ILogger)
? new LoggerResolverPolicy(parameter.Member.DeclaringType)
: base.CreateResolver(parameter);
}
}
class LoggerResolverPolicy : IDependencyResolverPolicy
{
private readonly Type _dependantType;
public LoggerResolverPolicy(Type dependantType)
{
_dependantType = dependantType;
}
public object Resolve(IBuilderContext context)
{
return new Logger(_dependantType);
}
}

The above extension works well but more configuration information is needed for MVC5 users. Here are the steps using unity.
Add the following line to the top of your startup.cs class above the namespace.
[assembly: log4net.Config.XmlConfigurator(ConfigFile ="Web.config", Watch = true)]
In your global.asax application_startup method add the following information:
log4net.Config.XmlConfigurator.Configure(new FileInfo(Server.MapPath("~/Web.config")));
The rest of the configuration to the unity container should be as is:
container.AddNewExtension<Log4NetExtension>();
Ensure you have an appender added to your web.config. That should be about it to get this working correctly. Good Luck

With Unity 5 and above, you can now use Unity's own Log4Net extension from https://github.com/unitycontainer/log4net.
All you have to do is install the Nuget and add the extension to your container:
container.AddNewExtension<Log4NetExtension>();
And it will work automatically with any classes that use ILog as a dependency.

You can use the following code to inject Log4Net
log4net.Config.BasicConfigurator.Configure();
container.RegisterType<ILog>(new InjectionFactory(x => LogManager.GetLogger(typeof(Program))));
typeof(Program) is used since I'm registering in program class. Use can use the class name or this keyword
Then you can inject ILog into the class
public class MyClass
{
private readonly ILog logger;
public MyClass(ILog logger)
{
this.logger = logger;
}
}

Related

Is there a way to Resolve log4net using Unity without calling ILog in the constructor?

So the way I usually do it (with DI) is to add the extension to my container:
unityContainer.AddNewExtension<Log4NetExtension>();
and then at the constructor of the class where I need to call the logger I use something like this:
public class test
{
private ILog logger;
public test (ILog logger)
{
this.logger =logger;
}
}
Now my problem is, in one of my classes, I don't want to pass anything to the constructor and I was wondering how can I assign my logger (since im using unity I thought of calling resolve but it's not working)
public class test
{
private ILog logger;
public test()
{
logger = unityContainer.Resolve<ILog>(); //I edited this for simplicity
}
}
Error is something like the container didn't know how to resolve ILog.
EDIT:
The class that didn't let me pass anything through its constructor is a Job (implements IJob) class, in the end I ended up using a job listener instead of logging in each job.
Some tips if you still want to pass something for the constructor is by implementation a Job Factory which should help you inject parameters. And I saw a nuget you can add to help you with Quartz integration with Unity.
Log4net allows you create a logger using a name in your class, no need to pass it via a constructor.
Add this as a class member
private static readonly log4net.ILog logger = log4net.LogManager.GetLogger("MyAppLog");
Of course, this does not use your DIContainer.
You can use property injection:
public class test
{
[Dependency]
public ILog Logger { get; set; }
public test()
{
}
}
Two drawbacks, though:
the logger's a public writable property now, so anyone could technically use or overwrite your logger
property injection is meant for optional dependencies, so you might be confusing others who look at the class

Ninject Get<T> with constructor argument

Here is my Module:
public class LoggerModule : NinjectModule
{
public override void Load()
{
Bind<ILogger>().To<NLogLogger>()
.WithConstructorArgument(
typeof(Type),
x => x.Request.ParentContext.Plan.Type);
}
}
So as you can see the NLogLogger is expecting the Type to be passed into the constructor.
This is my Unit Test:
[Test]
public void ResolveLoggerDependency()
{
var module = new LoggerModule();
var kernal = new StandardKernel(module);
var service = kernal.Get<ILogger>(new ConstructorArgument("type", typeof(int)));
Assert.That(service, Is.Not.Null);
}
It is throwing a null reference error on the kernal.Get<ILogger> so I can only assume I am not passing the constructor value correctly. How can I pass in a Type when using Get<T>?
So, this question as it seems relates to your other question.
The requirement in that question was to inject into NLogLogger the type of the object into which the it will be injected.
The registration in this case is assuming that this interface ILogger will not be resolved outside the context of a parent class into which it will be injected. And you are getting the exception because there is no parent class context when you directly attempt to resolve the ILogger interface.
I am assuming that in your unit test, your would like to test that this registration actually work. I would suggest the following:
First, create a class the you will use in your tests:
public class TestClass
{
private readonly ILogger m_Logger;
public TestClass(ILogger logger)
{
m_Logger = logger;
}
public ILogger Logger
{
get { return m_Logger; }
}
}
And then use such class in your unit tests like this:
[Test]
public void ResolveLoggerDependency()
{
var module = new LoggerModule();
var kernal = new StandardKernel(module);
var test_object = kernal.Get<TestClass>();
Assert.That(test_object.Logger, Is.Not.Null);
}
You can further verify that the NLogLogger actually used the TestClass class's name to construct the NLog logger. This might require the use of Reflection though, I am not sure.
In your Load method you can just set it up using Bind<ILogger>().To<NLogLogger>();

Implementation and usage of logger wrapper for log4net

This question is related to Steven’s answer - here. He proposed a very good logger wrapper. I will paste his code below:
public interface ILogger
{
void Log(LogEntry entry);
}
public static class LoggerExtensions
{
public static void Log(this ILogger logger, string message)
{
logger.Log(new LogEntry(LoggingEventType.Information,
message, null));
}
public static void Log(this ILogger logger, Exception exception)
{
logger.Log(new LogEntry(LoggingEventType.Error,
exception.Message, exception));
}
// More methods here.
}
So, my question is what is the proper way to create implementation that proxies to log4net? Should I just add another Log extension method with type parameter and then create a switch inside? Use different log4net method in case of LoggingEventType ?
And second question, what is the best way to use it later in the code?
Because he wrote:
(…) you can easily create an ILogger implementation (…) and configure
your DI container to inject it in classes that have a ILogger in their
constructor.
Does that mean that every class that will log sth (so basically every), should have ILogger in its constructor?
So, my question is what is the proper way to create implementation that proxies to log4net?
you should create something like:
public class Log4netAdapter : ILogger
{
private readonly log4net.ILog m_Adaptee;
public Log4netAdapter(log4net.ILog adaptee)
{
m_Adaptee = adaptee;
}
public void Log(LogEntry entry)
{
//Here invoke m_Adaptee
if(entry.Severity == LoggingEventType.Debug)
m_Adaptee.Debug(entry.Message, entry.Exception);
else if(entry.Severity == LoggingEventType.Information)
m_Adaptee.Info(entry.Message, entry.Exception);
else if(entry.Severity == LoggingEventType.Warning)
m_Adaptee.Warn(entry.Message, entry.Exception);
else if(entry.Severity == LoggingEventType.Error)
m_Adaptee.Error(entry.Message, entry.Exception);
else
m_Adaptee.Fatal(entry.Message, entry.Exception);
}
}
Does that mean that every class that will log sth (so basically every), should have ILogger in its constructor?
As I understand from Stevens answer: Yes, you should do this.
what is the best way to use it later in the code?
If you are using a DI container, then just use the DI container to map ILogger to Log4netAdapter. You also need to register log4net.ILog, or just give an instance of log4net logger to the DI container to inject it to the Log4netAdapter constructor.
If you don't use a DI container, i.e., you use Pure DI, then you do something like this:
ILog log = log4net.LogManager.GetLogger("MyClass");
ILogger logging_adapter = new Log4netAdapter(log);
var myobject = new MyClass(other_dependencies_here, logging_adapter);

Castle Windsor: How to specify different implementations for different properties of the same type [duplicate]

While registering components in Castle Windsor, how do we bind specific implementation of an interface to a component that has a dependency on that interface. I know in advance which implementation needs to be used by the component.
For example i created a sample console application based on code from several blogs and tutorials.
Following is the code.
public interface IReport
{
void LogReport();
}
public interface ILogger
{
string Log();
}
public class FileLogger : ILogger
{
public string Log()
{
return "Logged data to a file";
}
}
public class DatabaseLogger : ILogger
{
public string Log()
{
return "Logged data to a database";
}
}
public class McAfeeService : IReport
{
private readonly ILogger _logger;
public McAfeeService(ILogger logger)
{
this._logger = logger;
}
public void LogReport()
{
string getLogResult = this._logger.Log();
Console.WriteLine("McAfee Scan has " + getLogResult);
}
}
public class NortonService : IReport
{
private readonly ILogger _logger;
public NortonService(ILogger logger)
{
this._logger = logger;
}
public void LogReport()
{
string getLogResult = this._logger.Log();
Console.WriteLine("Norton Scan has " + getLogResult);
}
}
class Program
{
private static IWindsorContainer container;
static void Main(string[] args)
{
// Register components
container = new WindsorContainer();
container.Register(Component.For<IReport>().ImplementedBy<NortonService>());
container.Register(Component.For<ILogger>().ImplementedBy<FileLogger>());
IReport service = container.Resolve<IReport>();
service.LogReport();
Console.ReadLine();
}
}
I would like NortonService to always use a Filelogger and McAfeeService to use a Database Logger.
In the above program i am unable to bind NortonService to FileLogger.
How to do it?
The above answers lead me to inline dependencies and the feature service override
Here is the registration code:
container.Register(Component.For<IReport>().ImplementedBy<NortonService>().Named("nortonService"));
container.Register(Component.For<ILogger>().ImplementedBy<FileLogger>());
container.Register(Component.For<ILogger>().ImplementedBy<DatabaseLogger>());
container.Register(
Component.For<IReport>().ImplementedBy<McAfeeService>().Named("mcafeeService")
.DependsOn(Dependency.OnComponent<ILogger, DatabaseLogger>())
);
IReport mcafeescan = container.Resolve<IReport>("mcafeeService");
mcafeescan.LogReport();
IReport nortonscan = container.Resolve<IReport>("nortonService");
nortonscan.LogReport();
Output:
McAfee Scan has Logged data to a database
Norton Scan has Logged data to a file
I had a problem very like this, two implementation of one interface and two implementation of another interface. I wanted to force usage of particular implementations of those interfaces.
My class structure looked like this -
I looked at the naming convention, but didn't really like it. Instead I used the following -
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(
Component.For<IMessageLoader>().ImplementedBy<MessageLoaderDatabase>()
,Component.For<IMessageLoader>().ImplementedBy<MessageLoaderFile>()
,Component.For<IMessageOfTheDayService>().ImplementedBy<MessageOfTheDayServiceDatabase>()
.DependsOn(Dependency.OnComponent<IMessageLoader, MessageLoaderDatabase>())
,Component.For<IMessageOfTheDayService>().ImplementedBy<MessageOfTheDayServiceFile>()
.DependsOn(Dependency.OnComponent<IMessageLoader, MessageLoaderFile>())
,Component.For<MessageOfTheDayController>().LifestyleTransient()
.DependsOn(Dependency.OnComponent<IMessageOfTheDayService, MessageOfTheDayServiceFile>())
);
Full info about this approach is here. In the source code provided with that post I show two other ways of achieving the same result.
If you want to do it at runtime, This can be acheived through IHandlerSelector. Write a class that implements IHandlerSelector. It provides a method SelectHandler which will let you define the condition for binding conditionally at runtime. A Handler in this case is a component in Windsor that participates in instance construction. Refer here for more details.
My answer maybe not the best one, you can use naming method to resolve multi implementation:
container.Register(Component.For(typeof(ILogger))
.ImplementedBy(typeof(FileLogger))
.Named("FileLoggerIoC")
.LifestylePerWebRequest() ,
Component.For(typeof(ILogger))
.ImplementedBy(typeof(DatabaseLogger))
.Named("DatabaseLoggerIoC")
.LifestylePerWebRequest());
In your calling functions, you need to resolve it by name :-
var fileLog = container.Resolve("FileLoggerIoC", typeof(ILogger));
var DbLog = container.Resolve("DatabaseLoggerIoC", typeof(ILogger));
Mine method maybe not the best one as people don't like service locator to get the components, you can use this as temporary solution.

looking for various way of implemention Dependency injection using unity

i am new in Dependency injection. i just got familiar how to implement dependency injection with Interface injection but we know that Dependency injection can be implemented with three way or may be more and those are :-
Interface injection: The service provides an interface which consumers must implement. The interface exposes specific behaviors at run time.
Setter injection: The dependent object exposes a “setter” method to inject the dependency.
Constructor injection: Dependencies are injected through the class constructor
so i am looking for few sample code which can help me to understand how to implement Dependency injection using either Setter injection or Constructor injection using unity. any help with small small code for different way of implementing dependency injection will be appreciated.
i know only Interface injection using unity. here is my code which works fine using Interface injection with unity.
public interface ILogger
{
void Write(string message);
}
We have define three classes as follows.
public class FileLogger : ILogger
{
public void Write(string message)
{
//Do somthing
}
}
public class SQLLogger : ILogger
{
public void Write(string message)
{
//Do somthing
}
}
public class WindowsEventLogger : ILogger
{
public void Write(string message)
{
//Do somthing
}
}
Need to register and map these classes with interface in configuration file (i.e. app.config).
<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 type="UnityTest.ILogger, UnityTest" alias="ILogger" />
<namespace name="UnityTest"/>
<container>
<register mapTo="UnityTest.FileLogger, UnityTest" name="MyFileLogger" type="ILogger"/>
<register mapTo="UnityTest.SQLLogger, UnityTest" name="MySQLLogger" type="ILogger"/>
<register mapTo="UnityTest.WindowsEventLogger, UnityTest" name="MyWindowsEventLogger" type="ILogger"/>
</container>
</unity>
Note: name attribute is important in register tag.
Finally we have to use this map into our code. So, we have to know that for which one is preferable for specific country.
A dictionary object can be use to keep this mapping as follows.
IDictionary<string, string> loggers = new Dictionary<string, string>();
loggers.Add("USA", "MyFileLogger");
loggers.Add("GBR", "MySQLLogger");
loggers.Add("IN", "MyWindowsEventLogger");
You can populate it from database, xml or another source, and now it's time to call the Write method.
IUnityContainer container = new UnityContainer();
container.LoadConfiguration();
ILogger logger = container.Resolve<ILogger>(loggers[objUser.countryCode]);
logger.Write("Hello World");
New question
I found a sample code for construction injection with unity but still one thing is not clear. Here is the code.
public class CustomerService
{
public CustomerService(LoggingService myServiceInstance)
{
// work with the dependent instance
myServiceInstance.WriteToLog("SomeValue");
}
}
IUnityContainer uContainer = new UnityContainer();
CustomerService myInstance = uContainer.Resolve<CustomerService>();
When we write uContainer.Resolve<CustomerService>(); then we are not sending any instance of LoggingService class then how we can create instance of CustomerService class because it's constructor require instance of LoggingService.
This area is not clear. Please explain to me how it works.
Another question is [Dependency] attribute: what it does, and when a method needs to be decorated with the [Dependency] attribute.
With your code as a base.
if you have some class that depends on ILogger, and you have a default registration for ILogger (a registration without name)
IUnityContainer container = new UnityContainer();
//fixed
//by default RegisterType will create new instance of the type every time
//the container resolves the dependancy
container.RegisterType<ILogger,SomeLoggerImplementation>();
container.RegisterType<Foo>();
container.RegisterType<Bar>();
//will create a new instance of SomeLoggerImplementation using a default ctor, pass it to the constructor of Foo and return the instance of Foo
//if SomeLoggerImplementation has some other dependancies they can be registered in the container too!
var foo = container.Resolve<Foo>();
//will create a new instance of SomeLoggerImplementation using a default ctor, create a new instance of Bar,
//Set the value of the Property Logger (but not the Logger2), and return the instance of Bar
var bar = container.Resolve<Bar>();
//Constructor injection
public class Foo
{
private ILogger _logger;
public Foo(ILogger logger)
{
//if Foo is resolved from the container , the value for the logger parameter will be provided from the container
_logger = logger;
}
}
//property injection
public class Bar
{
//If Bar is resolvced from the container the value for the Logger property will also be provided from the container
[Dependency]
public ILogger Logger { get; set; }
//this will not be injected
public ILogger Logger2 { get; set; }
public Bar()
{
}
}
First register the classes to be solved to unity (in this case register Test class to unity). When you try to resolve an instance of Test class using unity, it will resolve ILogger too. You may refer to injection attributes from msdn
setter injection;
public class Test : ITest
{
[Dependency("MyFileLogger")]
public ILogger Logger
{
get { return iLogger; }
set { iLogger = value; }
}
}
constructor injection;
public class Test : ITest
{
public Test([Dependency("MyFileLogger")] ILogger logger)
{
//// you will have an instance of MyFileLogger
}
}
For the second part of your question, since LoggingService is also registered to unity, when CustomerService is tried to be resolved, it will use constructor injection to resolve the LoggingService parameter. In other words, when container tries to resolve CustomerService; it understands that LoggingService is needed to resolve it. Then it first resolves LoggingService parameter and then tries to resolve CustomerService.

Categories

Resources