0

I am using Unity.WwebAPI in my web api project. It is installed at Service level where i have my controller classes. Its all working fine.

Now i am trying to create a wrapper class in separate logging project so that i can use unity log4net extenstion across different layer in my solution.

How can i register unity log4net extenstion in my logging project? I know how to do it in UnityConfig file in service layer but i want to have this in logging project so that my log message method can be accessed in different layers

container.AddNewExtension< Log4NetExtension >();

Here is my test wrapper class;

Unity Log4Net wrapper class

 public class LogWrapper : ILogWrapper
{
    private readonly ILogWrapper _logWrapper;
    private ILog _log;

    public LogWrapper(ILogWrapper logWrapper)
    {
        _logWrapper = logWrapper;
    }

    public void LogMessage(string msg)
    {
        _log.Info(msg);
    }
}
user1263981
  • 2,953
  • 8
  • 57
  • 98
  • 1
    Why are you injecting logWrapper interface? Isn't it the same class as LogWrapper? Maybe you need to inject ILog instead, and everywhere where you need to use logger (i.e. services/repos) inject the ILogWrapper class – Ivvan Nov 16 '18 at 11:53

1 Answers1

1

Having the custom logger

Logging Project

public interface ILogger {
     void LogMessage(string msg);
}

so as not to couple your code to the 3rd party logger is a good idea.

Root Project

public class Log4NetWrapper : ILogger {
    private readonly ILog log; //log4net 

    public Log4NetWrapper(ILog log) {
        this.log = log;
    }

    public void LogMessage(string msg) {
        log.Info(msg);
    }

    //...
}

All that is left is to register your custom logger along with the 3rd party extension to the container in the composition root.

Root Project (Composition Root)

container = new UnityContainer();

//...

container.AddNewExtension<Log4NetExtension>();

//...

container.RegisterType<ILogger, Log4NetWrapper>(new HierarchicalLifetimeManager());

And use your internal logger where needed in the different layers.

public MyService(ILogger log) {
    //...
}

by using this abstraction the other layers do not need to know what is being used behind the scene to do the logging.

Only the composition root would need to be aware of the 3rd party dependency in order to register it with the IoC container.

Nkosi
  • 235,767
  • 35
  • 427
  • 472
  • Log4NetExtension is installed in different layer, do i still need to register this in unity container which is in service layer – user1263981 Nov 16 '18 at 12:59
  • 1
    registration tends to happen in the composition root – Nkosi Nov 16 '18 at 13:00
  • for this i would have to reference log4net in my service project. Whole idea is to have a separate class library for logging which can be used in any other projects. – user1263981 Nov 16 '18 at 13:03
  • 1
    technically only the root project will need to know about the 3rd party logger – Nkosi Nov 16 '18 at 13:04
  • so do i need to install extension in service project? – user1263981 Nov 16 '18 at 13:06
  • No you do not. Other layers only need to reference the project where your custom logger is defined. – Nkosi Nov 16 '18 at 13:07
  • i get reference error on line container.AddNewExtension(); in unity config file – user1263981 Nov 16 '18 at 13:08
  • In what layer do you populate the container? – Nkosi Nov 16 '18 at 13:10
  • log4net and unity log4net extenstion is installed in logging project. The unity.WebApi is installed in service (web) layer. – user1263981 Nov 16 '18 at 13:12
  • okay i got what you are saying. I am going to install unity log4net extention in service web layer and then i will try to inject the Ilog to other layer. Is this a right approach? Should i install log4net in service layer as well? – user1263981 Nov 16 '18 at 13:19
  • @user1263981 No. Do not inject `ILog` into the other layer. Your logger layer would have the definition of the abstraction. The implementation will live in the service web layer and consume the external dependency. The custom logger will be passed to the other layers. – Nkosi Nov 16 '18 at 13:23
  • is Composition Root my service layer? – user1263981 Nov 16 '18 at 13:25
  • @user1263981 check http://blog.ploeh.dk/2011/07/28/CompositionRoot/ and https://stackoverflow.com/questions/6277771/what-is-a-composition-root-in-the-context-of-dependency-injection – Nkosi Nov 16 '18 at 13:27
  • got it thanks. Where do i need to install log4net and its extention? In logging or service layer? – user1263981 Nov 16 '18 at 13:32
  • You mentioned service web and service layer. Are they the same? – Nkosi Nov 16 '18 at 13:48
  • sorry for the confusion; yes both are same – user1263981 Nov 16 '18 at 13:50
  • then yes to reference/install in service layer – Nkosi Nov 16 '18 at 13:51
  • i am getting this error when i run my application Method 'IsRegistered' in type 'Unity.UnityContainer' from assembly 'Unity.Container, Version=5.2.0.0, Culture=neutral, PublicKeyToken=489b6accfaf20ef0' does not have an implementation. – user1263981 Nov 16 '18 at 14:39
  • @user1263981 check https://stackoverflow.com/questions/11406298/method-x-from-type-y-in-assembly-z-does-not-have-an-implementation – Nkosi Nov 16 '18 at 14:50
  • @user1263981 found another https://stackoverflow.com/questions/948785/typeloadexception-says-no-implementation-but-it-is-implemented#948787 – Nkosi Nov 16 '18 at 14:52
  • i am going to start again as i am not able resolve last error message. To get this right this time, on which layer i need to install unit.log4net? Logging project or api service (have all controllers) project? or i need to add on both layers (don't make any sense)? – user1263981 Nov 16 '18 at 16:10