NLog GetCurrentClassLogger() NullReferenceException using StructureMap (Full Trust)
Asked Answered
M

1

12

It seems like NLog can't use reflection for GetCurrentClassLogger(), even though my MVC 3 app is deployed in a Full Trust environment on IIS7. I'm using StructureMap 2.6.1 and the problem seems to appear sporadically between deploys. I can't figure out why, though I don't think StructureMap is causing it.

Bootstrapper class:

public static class Bootstrapper
{
    public static void ConfigureStructureMap()
    {
        ObjectFactory.Initialize(Init);
    }

    private static void Init(IInitializationExpression x)
    {
        x.AddRegistry(new DBServiceRegistry());
        x.AddRegistry(new MyRegistry());
    }
}

Registry class:

public class MyRegistry : Registry
{
    public MyRegistry()//HttpContext context)
    {
        For<ILogger>().Use<NLogLogger>();
        For<IUserRepository>().Use<SqlUserRepository>();
    }
}

Everything works great on my machine. Why am I getting a System.NullReferenceException: Object reference not set to an instance of an object error when deploying?

[NullReferenceException: Object reference not set to an instance of an object.]
   NLog.LogManager.GetCurrentClassLogger() +84
   lambda_method(Closure , IArguments ) +40
   StructureMap.Construction.<>c__DisplayClass2.<CreateBuilder>b__0(IArguments args) +22
   StructureMap.Construction.InstanceBuilder.BuildInstance(IArguments args) +12
   StructureMap.Pipeline.ConstructorInstance.Build(Type pluginType, BuildSession session, IInstanceBuilder builder) +88

[StructureMapException: StructureMap Exception Code:  207
Internal exception while creating Instance '38000383-149d-45c2-a8f3-7442316da725' of PluginType Todo.Data.ILogger.  Check the inner exception for more details.]
   StructureMap.Pipeline.ConstructorInstance.Build(Type pluginType, BuildSession session, IInstanceBuilder builder) +276
   StructureMap.Pipeline.ConstructorInstance.build(Type pluginType, BuildSession session) +41
   StructureMap.Pipeline.SmartInstance_1.build(Type pluginType, BuildSession session) +43
   StructureMap.Pipeline.Instance.createRawObject(Type pluginType, BuildSession session) +45
   StructureMap.Pipeline.Instance.Build(Type pluginType, BuildSession session) +36
   StructureMap.Pipeline.ObjectBuilder.Resolve(Type pluginType, Instance instance, BuildSession session) +103
   StructureMap.BuildSession.CreateInstance(Type pluginType, Instance instance) +49
   StructureMap.<>c__DisplayClass3.<.ctor>b__1() +22
   StructureMap.BuildSession.CreateInstance(Type pluginType) +24
   ...etc...snipped
Malm answered 23/12, 2010 at 13:43 Comment(2)
I am having the same issue. Is there any workaround other than replacing NLog with NullLogger?Fester
@Fester not that I know of.Malm
M
28

Turns out it's not a trust issue, but an IoC issue. Thanks to an NInject solution for steering me in the right direction.

Solution

For your logging wrapper, use a constructor that accepts a string parameter:

public class NLogLogger : ILogger
{
    private Logger _logger;

    public NLogLogger(string currentClassName)
    {
        _logger = LogManager.GetLogger(currentClassName);
    }
    ...
}

NLog StructureMap Config:

For<ILogger>().Use<NLogLogger>()
    .Ctor<string>("currentClassName")
    .Is(x => x.BuildStack.Root.RequestedType.FullName);
Malm answered 24/12, 2010 at 9:38 Comment(2)
It can be done this way as well: x.For<ILogger>().Use( context => new NLogLogger( context.ParentType ) );Liddy
I used this solution, but with the ILogger wrapper as suggested in the "logger wrapper best practice" answer at https://mcmap.net/q/222643/-logger-wrapper-best-practice to save on maintaining my own ILogger wrapper. At least until NLog ever gets around to adding their own interface.Lissettelissi

© 2022 - 2024 — McMap. All rights reserved.