2011-08-08 53 views
1

我不知道如何陈述这个问题,因为我不知道问题出在哪里。我认为它是一个基因协变问题,但是解决方案可能在其他地方找到,也可能以接口的设计方式,或者实现的注册方式。Autofac注册和解析类型实现通用interace

无论如何,该示例试图注册所有实现通用接口的类型,然后使用通用类型解析该类型。然后尝试将此类型转换为其基本类型,以便能够在该实现上调用方法。

尝试投射时,它现在失败。作为一个例子,第一行代码无法编译。当被移除时,程序在尝试转换实现的行上失败。

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..."); 
    } 
} 

回答

2

这是行不通的。
以下是原因:
IHandler<IConfiguration>需要IConfiguration作为Handle的参数。
如果你的第一线将是有效的,下面将进行编译:

MyOtherConfiguration config = new MyOtherConfiguration(); 
IHandler<IConfiguration> test = new MyHandler(); 
test.Handle(config); 

显然,这是不正确的,因为MyHandler.Handle想要一个MyConfiguration或派生类型。

使用在我先前的这个答案的版本描述禁忌变化将允许你做到以下几点:

IHandler<MyDerivedConfiguration> test = new MyHandler(); 

MyDerivedConfigurationMyConfiguration得到的。

+0

试过了,它仍然不起作用。试过了T也是,这个赋值工作,但不是编译器的实现不会执行。 – MatteS

+0

@MatteS:你说得对。请参阅最新的答案。 –

+0

非常感谢,现在它完全清楚为什么这不起作用。我认为生病不得不重新考虑我的设计。或者如果不是这样,也许可以通过反射来调用我的处理程序。 – MatteS