Search code examples
c#castle-windsor

Castle Windsor registration of types different from those used in type discovery


Let's say I have the following:

public interface IMyInterface<T>
{
}

public interface IMyClass<T>
{
}

public class MyClass<T, T2> : IMyClass<T2>
    where T : IMyInterface<T2>
{
}

foreach(/*var impl in classes_that_implement_IInterface<T>*/)
{
    //register IMyClass<T> as MyClass<typeof(impl), T>
}

e.g. If I defined

public class MyImplementation : IMyInterface<string>
{
}

the following will be registered:

IMyClass<string> as MyClass<MyImplementation, string>

Is there a neat way to do this? I can't think how to approach this :/


Solution

  • Ok I did this.. but it seems rather... abusive?

    var container = new WindsorContainer();
    
    container.Register(
        Classes.FromThisAssembly()
            .BasedOn(typeof(IMyInterface<>))
            .Configure(x =>
            {
                var iMyInterfaceImpl = x.Implementation;
    
                var iMyInterface = iMyInterfaceImpl
                    .GetTypeInfo()
                    .GetInterfaces()
                    .Where(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IMyInterface<>))
                    .Single();
    
                var iMyInterfaceGenericArg0 = iMyInterface.GetGenericArguments()[0];
    
                var myClassImpl = typeof(MyClass<,>).MakeGenericType(iMyInterfaceImpl, iMyInterfaceGenericArg0);
                var iMyClass = typeof(IMyClass<>).MakeGenericType(iMyInterfaceGenericArg0);
    
                container.Register(Component.For(iMyClass).ImplementedBy(myClassImpl));
            })
    );
    
    
    container.Resolve(typeof(IMyClass<string>)); // MyClass<MyImplementation, string>