Autofac register and resolve types implementing a generic interace
Im not sure how to state this question, because im not sure where the problem lies. I think its a genetric covariance issue, but the solution might be found somewhere else, maybe in the way the interfaces are designed, or in how the implementations are registered.
Anyway, the sample is trying to register all types implementing a generic interface, then later resolve the type using the type of the generic. Then trying to cast this type to its base type to be able to call a method on that implementation.
Its now failing when trying to cast. As an example, the first line of code fails to compile. When removed, the program fails on the line trying to cast the implementation.
class Program
{
private static IContainer _container;
static void Main(string[] args)
{
// Is this the problem?
IHandler<IConfiguration> test = new MyHandler();
// setup ioc
var builder = new ContainerBuilder();
builder.RegisterAssemblyTypes(typeof(Program).Assembly)
//.Where(t => typeof(IHandler<IConfiguration>).IsAssignableFrom(t));
.Where(t => t.GetInterfaces()
.Where(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IHandler<>))
.Any()
)
.As(t => t.GetInterfaces()
.Where(i => i.GetGenericTypeDefinition() == typeof(IHandler<>))
.Single()
);
_container = builder.Build();
// get开发者_运维技巧 my configuration impl
var configuration = new MyConfiguration();
// resolve handler for the configuration
var configurationType = configuration.GetType();
var handlerGenericType = typeof(IHandler<>);
var handlerType = handlerGenericType.MakeGenericType(configurationType);
var handler = _container.Resolve(handlerType);
var typedHandler = (IHandler<IConfiguration>) handler;
// handle it!
typedHandler.Handle(configuration);
}
}
public interface IConfiguration
{
}
public interface IHandler<T> where T : IConfiguration
{
void Handle(T myConfiguration);
}
public class MyConfiguration : IConfiguration
{
}
public class MyHandler : IHandler<MyConfiguration>
{
public void Handle(MyConfiguration myConfiguration)
{
Console.WriteLine("Handling my stuff...");
}
}
There is no way this is going to work.
Here is the reason why:
An IHandler<IConfiguration>
requires an IConfiguration
as parameter to Handle
.
If your first line would be valid, the following would compile:
MyOtherConfiguration config = new MyOtherConfiguration();
IHandler<IConfiguration> test = new MyHandler();
test.Handle(config);
Obviously, this is not correct, because MyHandler.Handle
wants a MyConfiguration
or derived type.
Using contra-variance as described in my earlier version of this answer would allow you to do the following:
IHandler<MyDerivedConfiguration> test = new MyHandler();
with MyDerivedConfiguration
being derived from MyConfiguration
.
精彩评论