2

У меня есть вопрос об Autofac: Как получить имя класса, запрашивающего экземпляр из контейнера?Autofac - Как получить имя класса при создании экземпляра

Возможно ли получить имя класса «Autofac_Test», переданного в конструктор autofac при создании объекта?

Мой код:

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; } 
} 
+1

Верно ли, что вы не можете/не хотите рассмотреть решения какой-нибудь ILogFactory вместо или обеспечить этот тип в качестве параметра вручную (так как вы используя локатор обслуживания здесь)? – Igor

+0

Возможно, я должен подумать, что вы сказали ... спасибо за помощь ... – Ruuteek

ответ

4

Для вашего конкретного случая это будет довольно трудно получить эту информацию. Но, насколько я понимаю, MyLogger должен знать имя типа, в которое оно будет введено, и пример кода может быть неактуальным.

В этом случае вы можете использовать модуль и Готовится событие:

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))), 
      }); 
     }; 
    } 
} 

Тогда вам придется зарегистрировать свой модуль так:

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

Теперь каждый раз, когда ILogger будет закачиваться к типу он будет иметь правильное имя.

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

    private readonly String _loggerName; 

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

LoggerName будет Foo.

Ваш тест может выглядеть следующим образом:

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

Спасибо за вашу помощь, но ваш код не работает. Может быть, я так устал. – Ruuteek

+0

@Ruuteek Что не работает? –

+0

в методе: void AttachToComponentRegistration (.... У меня есть исключение: Autofac.Core.DependencyResolutionException: Исключение было выбрано при вызове конструктора «Void .ctor (System.Type)» в типе «MyLogger». --- > Невозможно применить объект типа «System.String» типа «System.Type». (См. Внутреннее исключение для подробностей.) – Ruuteek

0

UPDATE

@Cyril Durand доказал, что это возможно. Предложение ниже верно, но не так.

Это не похоже, что autofac поддерживает то, что вы хотите. Вы можете вызвать столбец разбора вызовов в конструкторе MyLogger, но это будет стоить вам производительности.

Там уже вопрос о очень похожей вещи и фабриках был предложен вместо

Autofac. Register class with constructor with params

Смежные вопросы