2015-03-06 2 views
0

У меня есть интерфейс IService и многие реализации IService в другой сборке. Мне нужно зарегистрировать все реализации как службу для типов, которые находятся в цепочке наследования между IService и конкретной реализацией IService. Например:Регистрация типов с StructureMap методом сканирования

public interface IService{} 
public abstract class BaseService<T>: IService{} 

А в другой сборке:

public class SomeSpecialService: BaseService<SomeType>{} 
public class AnotherSpecialService: BaseService<AnotherType>{} 

Итак, мне нужно зарегистрировать SomeSpecialService как сервис для BaseService<SomeType> и AnotherSpecialService как сервис для BaseService<AnotherType>.

В настоящее время я делаю это посредством отражения с регистрацией каждой реализации по одному.

1) Возможно ли использование выражения Scan()?

2) Возможно ли использование выражения Scan(), если SomeSpecialService является внутренним (непубличным) классом в другой сборке?

ответ

2

Вы можете сделать это с:

 var container = new Container(
      c => c.Scan(
       s => 
        { 
         s.TheCallingAssembly(); 
         s.AddAllTypesOf(typeof(BaseService<>)); 
        })); 

Если у вас есть несколько реализаций BaseService<> для конкретного родового аргумента (например, BaseService<SomeType>), необходимо регистрации имен и разрешать их по имени.

 var container = new Container(
      c => c.Scan(
       s => 
        { 
         s.TheCallingAssembly(); 
         s.AddAllTypesOf(typeof(BaseService<>)).NameBy(t => t.Name); 
        })); 

     var service = container.GetInstance<BaseService<SomeType>>("BaseServiceForSomeType"); 

Если у вас есть только одна реализация каждого родового аргумента, и вы должны иметь, кроме жизненного цикла по умолчанию (Transient), то вы можете использовать s.ConnectImplementationsToTypesClosing(typeof(BaseService<>)).OnAddedPluginTypes(c => c.Singleton());

Когда вам нужно еще больше настроек при регистрации типов, то вы можете определить вы регистрируетесь.

 public class BaseServiceConvention : IRegistrationConvention 
     { 
      public void Process(Type type, Registry registry) 
      { 
       if (!type.IsConcrete()) 
       { 
        return; 
       } 

       var interfaceTypes = type.FindInterfacesThatClose(typeof(BaseService<>)); 

       foreach (var closedGenericType in interfaceTypes) 
       { 
        if (GenericsPluginGraph.CanBeCast(closedGenericType, type)) 
        { 
         registry.For(closedGenericType).Singleton().Use(type).Named(type.Name); 
        } 
       } 
      } 
     } 

И применять это соглашение, как это:

 var container = new Container(
       c => c.Scan(
        s => 
         { 
          s.TheCallingAssembly(); 
          s.Convention<BaseServiceConvention>(); 
         })); 

Надеется, что это помогает!

+0

Что делать с регистрацией внутренних типов из другой сборки? – Albert

+0

@Albert, к сожалению, я не могу придумать способ автоматической регистрации внутренних типов. Я не думаю, что это возможно, поэтому вам придется создавать типы, необходимые для регистрации общественности (если это возможно). – LetMeCodeThis

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