StructureMap: многопоточный env. Не определен экземпляр по умолчанию для PluginFamily - PullRequest
3 голосов
/ 02 октября 2011

Я давно имею дело с ошибкой структурной карты. Ошибка:

StructureMap.StructureMapException: Код исключения StructureMap: 202 Не определен экземпляр по умолчанию для PluginFamily SomeNamespace.ISomeInterface, SomeNamespace, Версия = 1.0.0.0, Культура = нейтральная, PublicKeyToken = ноль

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

Настройка StructureMap выполняется при запуске приложения. Я использую StructureMap.Configuration.DSL.Registry:

var registry = new Container(...some parameters settings...);
StructureMap.ObjectFactory.Configure(x => x.IncludeRegistry(registry));

А контейнер это:

class Container : StructureMap.Configuration.DSL.Registry
{
    public Container(...Some settings parameters...)
    {
        For<IConnG>().Use<DG>()
            .Ctor<string>("user").Is(some parameter)
            .Ctor<string>("pass").Is(some parameter)
            .Ctor<string>("site").Is(some parameter)
            .Ctor<string>("DateFormat").Is(some parameter);

        For<IRPG>().Use<RPG>();

        Scan(asm =>
        {
            asm.TheCallingAssembly();
            asm.Include(type => type.IsAbstract == false && type.IsSubclassOf(typeof(BaseC)));
            asm.With(new RegistrationConvention());
        });

        var actionName = (enumA)Enum.Parse(typeof(enumA), some parameter);

        switch (actionName)
        {
            case enumA.ActionA:
                Profile(enumA.ActionA.ToString(), (pe) =>
                {
                    pe.For...;
                    pe.For...;
                    pe.For...;
                    pe.For<IXXX>().Use<DefaultXXX>();
                    **pe.For<IAction<SomeNamespace.SearchParams, SomeNamespace.SearchParams>>().Use<DefaultSearchParams>();**
                    pe.For...;
                });
                break;

            case enumA.ActionB:
                Profile(enumA.ActionB.ToString(), (pe) =>
                {
                    pe.For...;
                    pe.For...;
                    pe.For...;
                    pe.For<IXXX>().Use<DefaultXXX>();
                    **pe.For<IAction<SomeNamespace.SearchParams, SomeNamespace.SearchParams>>().Use<DefaultSearchParams>();**
                    pe.For...;
                });
                break;

            case enumA.ActionC:
                Profile(enumA.ActionC.ToString(), (pe) =>
                {
                   pe.For...;
                    pe.For...;
                    pe.For...;
                    pe.For<IXXX>().Use<DefaultXXX>();
                    **pe.For<IAction<SomeNamespace.SearchParams, SomeNamespace.SearchParams>>().Use<XXXSearchParams>();**
                    pe.For...;
                });
                break;

            case enumA.ActionD:
                Profile(enumA.ActionD.ToString(), (pe) =>
                {
                    pe.For...;
                    pe.For...;
                    pe.For...;
                    pe.For<IXXX>().Use<DefaultXXX>();
                    **pe.For<IAction<SomeNamespace.SearchParams, SomeNamespace.SearchParams>>().Use<DefaultSearchParams>();**
                    pe.For...;
                });
                break;
        }
    }
}

Регистрационный Конвенция:

public class RegistrationConvention : StructureMap.Graph.IRegistrationConvention
{
    #region IRegistrationConvention Members

    public void Process(Type type, StructureMap.Configuration.DSL.Registry registry)
    {
        var interfaces = new List<Type>
        {
            type.GetInterface("IInfo`1"),
            type.GetInterface("IBook`1"),
            type.GetInterface("IConf`1"),
            type.GetInterface("IClxP`1"),
            type.GetInterface("ICanc`1"),
            type.GetInterface("IConf2`1"),
            type.GetInterface("IMaxP`1"),
            type.GetInterface("IAction`1")
        };

        interfaces
            .ForEach(contractType =>
                     {
                         if (contractType != null)
                         {
                             registry.For(contractType).Use(type);
                         }
                     });
    }

    #endregion
}

Я вызываю StructureMap в таком коде:

var container = StructureMap.ObjectFactory.Container;

container.SetDefaultsToProfile(Some profile name);

var adaptor = container.GetInstance<IAction<SomeNamespace.SearchParams, SomeNamespace.SearchParams>>();

Этот код вызывается многими потоками, и я получаю эту ошибку не всегда, а довольно часто. При печати WhatDoIHave () это указывает, что оно есть.

Я буду рад любому предложению / исправлению. Заранее спасибо.

1 Ответ

3 голосов
/ 05 октября 2011

Трудно было решить, но наконец я туда попал!Проблема заключалась в том, что я неправильно использовал StructureMap: StructureMap, насколько я правильно понял, намерение его использовать, предназначен для динамической загрузки настроек один раз, когда загружается приложение.В нашем проекте мы переключаем профили много раз в секунду и пытаемся извлечь экземпляр на основе этого профиля.Мы получили много исключений, например, он не распознает экземпляр по умолчанию, хотя WhatDoIHave () показал обратное.Проблема была именно в этом - вызывая Контейнер из множества потоков и переключая профили при каждом запросе.

Итак, для напоминания, когда приложение запускается, для каждого профиля я добавил свои настройки только в один Контейнер:

var registry = new OurRegistry(settings parameters..., profileName);

StructureMap.ObjectFactory.Configure(x => x.IncludeRegistry(registry));

И во многих местах кода я обычно называл StructureMap следующим образом:

  var container = StructureMap.ObjectFactory.Container;

  container.SetDefaultsToProfile(profileName);

  var adaptor = container.GetInstance<ISomeInterface<ConcreteType>>();

Этот код использовался параллельно, и каждый поток использовал другой профиль.

Итак, в качестве исправления я создал контейнер для профиля!

var registry = new OurRegistry(settings parameters..., profileName);

var container = new StructureMap.Container(registry);

И я сохранил каждый контейнер в нашем коде, а не в StructureMap, как раньше, поэтому каждый поток, подверженный профилю, используетэто собственный профилированный контейнер.Это даже быстрее, чем раньше, потому что вам не нужно так много переключать профили, только один раз!

И не более # $ @! @ 202 исключение:)

...