Autofac - How to get class name on instantiation

I have a question about Autofac: How can I get the name of the class requesting an instance from the container?

Is it possible to get the name of the Autofac_Test class passed to the autofac constructor when creating an object?

My code:

using System;
using System.Diagnostics;
using System.Reflection;
using Autofac;
using Xunit;

public class BootStrap
{
    public IContainer Configure()
    {
        var builder = new ContainerBuilder();
        builder.Register(b => new MyLogger(MethodBase.GetCurrentMethod().ReflectedType)).As<ILog>();
        return builder.Build();
    }
}
public class Autofac_Test
{
    private IContainer _containter;
    public Autofac_Test()
    {
        _containter = new BootStrap().Configure();
    }
    [Fact]
    public void Should_create_class_with_Name_BlaBla()
    {
        var logger = _containter.Resolve<ILog>();
        Assert.True(logger.Name == "Autofac_Test");
    }
}
public class MyLogger : ILog
{
    public string Name { get; private set; }
    public MyLogger(Type name)
    {
        Name = name.FullName;
    }
    public void Info(string message)
    {
        Debug.WriteLine(string.Format("{0} {1}", Name, message));
    }
}

public interface ILog
{
    void Info(string message);
    string Name { get; }
}

      

+3


source to share


2 answers


In your particular case, getting this information will be quite difficult. But as I understand it, MyLogger

you need to know the name of the type in which it will be entered, and the sample code may be out of date.

In this case, you can use module and preparatory event:

public class LoggingModule : Autofac.Module
{
    protected override void AttachToComponentRegistration(
        IComponentRegistry componentRegistry, IComponentRegistration registration)
    {
        registration.Preparing += (sender, e) =>
        {
            Type limitType = e.Component.Activator.LimitType;
            e.Parameters = e.Parameters.Union(new[] {
                new ResolvedParameter((pi, c) => pi.ParameterType == typeof(ILogger), 
                                      (pi, c) => c.Resolve<ILogger>(new NamedParameter("name", limitType.Name))),
            });
        };
    }
}

      

Then you will need to register your module like this:

ContainerBuilder builder = new ContainerBuilder();
builder.RegisterModule<LoggingModule>();
builder.RegisterType<MyLogger>().As<ILogger>();

      



Now, every time a ILogger

is entered into a type, it will have the correct name.

class Foo
{
    public Foo(ILogger logger)
    {
        this._loggerName = logger.Name;
    }

    private readonly String _loggerName; 

    public String LoggerName 
    {
        get 
        {
            return this._loggerName;
        }
    }
}

      

LoggerName

will be Foo

.

Now your test might look like this:

[Fact]
public void Should_create_class_with_Name_BlaBla()
{
    var foo = _containter.Resolve<Foo>();
    Assert.AreEquals("foo", foo.LoggerName, "invalid loggerName");
}

      

+5


source


UPDATE

@Kirill Duran proved it. The suggestion below is correct, but not true.

It doesn't seem like autofac supports what you want. You can call the parsing session stack in the constructor of MyLogger, but it will cost you performance.



We already have a question about a very similar thing and factory

Autofac. Register a class with a constructor with parameters

0


source







All Articles