Как я могу зарегистрировать несколько универсальных компонентов с несколькими универсальными сервисами в Castle Windsor? - PullRequest
1 голос
/ 06 марта 2012

Я использую Castle Windsor 3.0 в .net 4.0 (c #), и у меня следующая ситуация:

namespace Root
{
    public interface IGenericService<T>
    {        
    }
    public class GenericService<T> : IGenericService<T>
    {        
    }
}    
namespace Root.A
{
    public class Something
    {        
    }
    //... Some other classes
}

Я хочу, чтобы в каждом контейнере была зарегистрирована реализация IGenericService для каждого классаон находится в том же пространстве имен, что и «Something».

Я могу сделать это следующим образом, но мне интересно, возможно ли использовать свободный интерфейс конфигурации Castle Windsor?

private static void RegisterComponents(IWindsorContainer container)
{            
    // Get all the types in the same namespace as "Something"
    // I.e AllTypes.FromThisAssembly().InSameNamespaceAs<Something>()
    var type = typeof(Something);
    var types = type
        .Assembly
        .GetTypes()
        .Where(t => t.Namespace != null &&
                    t.Namespace.Equals(type.Namespace,
                                       StringComparison
                                           .InvariantCultureIgnoreCase));

    // For each of those types register a component GenericService<T>
    // with service IGenericService<T> where T is each type
    Type genericBaseType = typeof(GenericService<>);
    string assemblyName = genericBaseType.Assembly.GetName().FullName;
    string genericBaseName = genericBaseType.FullName;
    foreach (var t in types)
    {
        var ser = typeof(IGenericService<>);
        var serAssemblyName = ser.Assembly.GetName().FullName;
        string serviceFullName = string.Format(
               CultureInfo.InvariantCulture,
               "{0}[[{1}]], {2}",
               ser.FullName,
               t.AssemblyQualifiedName,
               serAssemblyName);
        var serviceType = Type.GetType(serviceFullName);


        string componentFullName = string.Format(
            CultureInfo.InvariantCulture,
            "{0}[[{1}]], {2}",
            genericBaseName,
            t.AssemblyQualifiedName,
            assemblyName);
        var componentType = Type.GetType(componentFullName);


        container.Register(Component
            .For(serviceType)
            .ImplementedBy(componentType)
            .LifestylePerWebRequest());
    }
}

Ответы [ 2 ]

0 голосов
/ 30 апреля 2012

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

0 голосов
/ 06 марта 2012

Как и любой другой контейнер IoC, Castle Windsor регистрирует типы глобально , что означает, что если вы зарегистрируете реализацию, скажем, интерфейса, у него будет область действия для всего приложения.Вы не можете ограничить его пространством имен.

Однако для этой ситуации есть обходной путь, в котором вы можете зарегистрировать с именем компонент, например

container.Register(Component
    .For(serviceType)
    .Named("NamespaceA")     //<------HERE
    .ImplementedBy(componentType_NamespaceA) //one type
    .LifestylePerWebRequest());

container.Register(Component
    .For(serviceType)
    .Named("NamespaceB")     //<------HERE
    .ImplementedBy(componentType_NamespaceB)  //another type
    .LifestylePerWebRequest());

СейчасВы можете определить нужный тип по интерфейсу и имени.

...