简体   繁体   中英

How can I register multiple generic components with multiple generic services in castle windsor?

I am using Castle Windsor 3.0 in .net 4.0 (c#) and I have the following situation:

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

What I want to do is have an implementation of IGenericService registered in the container for every class that is in the same namespace as "Something".

I can do it like this but I am wondering, is it possible using the Castle Windsor fluent configuration API?

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

经过很长时间的搜索,我认为答案是您做不到,问题中发布的代码是实现此目标的唯一方法,是的,这是相当麻烦的事,并着眼于应用程序从整体上讲,在大多数情况下可能会有更好的设计。

As any other IoC container Castle Windsor registers types globally , which means if you register an implementation of say an interface, it has a scope for the whole application. You cannot limit it to a namespace.

However, there is a workaround for this situation, where you can register a named component, for example

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());

Now you can resolve the type that you need by the interface and name.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM