2017-09-03 203 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();