StructureMap получить запрошенный тип - PullRequest
3 голосов
/ 15 октября 2010

Можно ли передать запрашивающий тип в качестве параметра при настройке контейнера StructureMap.

Например:

            container.Configure(x => {
                x.For<ILogger>().Use(new TestLogger(log.Add, requestingType));         
            });

Где запрашивающий тип - это тип объекта-потребителя:

public class SomeClass
{
    private readonly ILogger logger;
    public SomeClass(ILogger logger)
    {
        this.logger = logger;
    }
}

Таким образом, тип, передаваемый регистратору, будет SomeNamespace.SomeClass.

Спасибо, Бен

Ответы [ 3 ]

3 голосов
/ 24 июля 2012

Вы можете легко получить доступ к запрошенному типу, используя IContext от StructureMap.

ObjectFactory.Configure(
    x => {
        x.For<ILogger>().Use( context => new TestLogger( context.ParentType ) );
    } );

В приведенном выше утверждении context.ParentType возвращает тип, создаваемый StructureMap.

Джереми Миллер также освещал эту тему в своем блоге. В статье используется устаревший синтаксис, но он по-прежнему актуален: http://codebetter.com/jeremymiller/2009/01/15/using-the-build-session-in-structuremap/

Если вы хотите проверить все доступные свойства в IContext, вы можете использовать анонимную функцию и установить точку останова на обратной строке следующим образом:

ObjectFactory.Configure(
    x => {
        x.For<ILogger>()
                .Use( context =>
                {
                    // Set breakpoint here and inspect the context
                    return new TestLogger( context.ParentType );
                } );
    } );

Обновление:

Убедитесь, что вы используете .AlwaysUnique () (что эквивалентно старому синтаксису .CacheBy (InstanceScope.Unique)), иначе StructureMap будет кешировать первый запрос ILogger, что приведет к тому, что исходный регистратор будет внедрен во все последующие запросы на ILogger во время одного вызова GetInstance ().

Это может легко произойти, если у вас есть вложенные классы, для каждого из которых требуется ILogger, поэтому запрос ObjectFactory.GetInstance () приведет к созданию ILogger для самого глубокого класса в иерархии, а затем все другие классы получат тот же самый экземпляр ILogger, который, скорее всего, то, что вы делаете , а не , которое должно произойти.

Итак, учитывая это обновление и совет Бена, вот лучшее решение:

x.For<ILogger>()
    .AlwaysUnique()
    .Use( c => new TestLogger( c.ParentType ?? c.BuildStack.Current.ConcreteType ) );
0 голосов
/ 16 октября 2010

Сначала я хочу указать на потенциальную ошибку, регистрация экземпляра с помощью Use (new Type ()) приводит к тому, что этот экземпляр регистрируется как одиночный.Чтобы избежать этого, вы можете использовать Use (() => new Type ()).

Вот как вы получаете запрошенный тип во время конфигурации:

container.Configure(x => {
  x.For<ILogger>().Use(c => new TestLogger(log.Add, c.Root.RequestedType));
});
0 голосов
/ 15 октября 2010

Я нашел решение здесь

В основном мы изменили интерфейс ILogger на ILogger<T> и использовали функцию вывода универсального типа в StructureMap.

Строго говоря, это не отвечает на мой вопрос о том, могу ли я получить запрашивающий тип, поэтому, если вы знаете, как это сделать, ответьте - было бы полезно знать.

...