2017-09-03 179 views
2

我有一个通用接口层次结构,其中每个接口都与IOperator<T1,T2>有关。实例化实现通用接口实例的所有类

interface IOperator<T1, T2> 
{ 
    Func<T1, T2, bool> GetFunc() 
} 

IOperator : IOperator<object, object> 

interface IMatchingOperator : IOperator<string, string> { } 


interface IComparisonOperator<T1, T2> : IOperator<T1, T2> 
    where T1: IComparable<T2> { } 

interface IComparisonOperator<T> : IComparisonOperator<T, T> 
    where T: IComparable<T> { } 

interface IComparisonOperator : IComparisonOperator<IComparable, object> 

我有很多的实现这些接口中的一个或多个类(不是一般的),例如:

class GreaterThanOperator : 
    IComparisonOperator, 
    IComparisonOperator<decimal>, 
    IComparisonOperator<DateTime>, 
    IComparisonOperator<DateTime, string> 
{ ... } 

class EqualComparator: IOperator 

class RegexOperator : IMatchingOperator { ... } 

现在,我想创建一个工厂,可以加载和实例组件中的每个类以某种方式实现父接口“IOperator”,并将其放入集合中。

我试着用:

AppDomain.CurrentDomain.GetAssemblies() 
       .SelectMany(x => x.GetTypes()) 
       .Where(
        x => x.IsGenericType 
        && x.GetGenericTypeDefinition() == typeof(IOperator<,>) 
        && !x.IsInterface && !x.IsAbstract)) 
       .Select(x => Activator.CreateInstance(x)).ToList(); 

,但它不工作。

我希望最终的列表能够容纳每个IOperator类的一个实例。 然后,我将用反射导航对象以查看它们使用的通用类型。

+0

第一个问题,为什么你想做到这一点,它看起来像你正在寻找'懒loading'技术。 –

+0

这将在工厂的静态构造函数中运行。原因是我想知道所有存在的运营商。我将如何实现延迟加载方法? – AFusco

+0

你可以在你需要的时候实例化类型,如果你想要的话,你也可以将它们缓存在静态属性中。 –

回答

2

Where子句不应检查泛型类型,因为您的类GreaterThanOperator等本身不是泛型类。另外,IOperator<,>而不是您的类型的定义:它是由它实现的接口之一的类型定义。

这里是你如何能进行选择:

var res = AppDomain.CurrentDomain.GetAssemblies() 
    .SelectMany(x => x.GetTypes()) 
    .Where(x => 
     !x.IsAbstract 
    && !x.IsInterface 
    && x.GetInterfaces().Any(i => 
      i.IsGenericType() 
     && i.GetGenericTypeDefinition() == typeof(IOperator<,>) 
     ) 
    ).Select(x => Activator.CreateInstance(x)).ToList();