2009-10-19 39 views
1

是否有任何好的算法來確定實例化的「最佳」類型以完成請求?.NET通用類型 - 尋找最具體的類型

例如說我有以下類:

public interface ISometype<T> {} 
public class SomeTypeImpl<T>:ISometype<T> {} 
public class SomeSpecificTypeImpl<T>:ISometype<T> where T: ISpecificSpecifier {} 
public interface ISpecificSpecifier { } 

假設主叫方希望此接口的最好實現類型。我可以實現這樣的這種特殊的方法:

public Type GetBestImplementationType(Type genericParam) { 
    try { 
     return typeof(SomeSpecificTypeImpl<>).MakeGenericType(genericParam); 
    } catch(ArgumentException) {} 
    return typeof(SomeTypeImpl<>).MakeGenericType(genericParam); 
} 

雖然實施這一項目,因爲我更關心的是一般化其中可能有不止一個潛在的具體實施以及多個通用參數這個特殊的情況下工作

public Type GetBestImplementationType(Type[] genericParams, Type[] potentialTypes) { 
    foreach(var t in potentialTypes) { 
     try { 
      return t.MakeGenericType(genericParams); 
     } catch(ArgumentException) {} 
    } 
    throw new Exception("unable to find specific implementation type"); 
} 

這應該工作給potentialTypes數組提供從大多數到最不特定的順序。因此,對於答案,要麼是實現這種方法的算法(或者足夠類似的東西),要麼是一種實現我可以在這種方法中使用的算法的算法。
[警告:代碼未經測試,可能存在語法/邏輯錯誤]

+1

這聽起來對我來說就像你想要一個IoC容器...... – 2009-10-19 19:17:13

+0

其實,我已經有一個:溫莎。這個問題與我今天早些時候在用戶列表中提出的關於選擇最佳實現類型的文章相關。我強烈懷疑,如果這個算法寫在某個地方,那麼它已經存在於其中一個IoC容器中。 – 2009-10-19 19:24:57

+0

藉助Windsor和流利的註冊API,您可以爲特定情況指定ServiceOverrides。 http://using.castleproject.org/display/IoC/Fluent+Registration+API – 2009-10-19 20:38:22

回答

0

看來:

  1. 有沒有更好的方法來確定是否一個泛型類型的滿足約束條件等,而不是試圖創建類型和捕獲異常(這是可以做到的,但似乎需要至少和異常方法一樣長,而且要複雜得多)。
  2. 由於#1,[計算]很難從大到小的順序排列一組類型。相反,在代碼中,我的解決方案是明確告訴我的容器如何訂購這些類型。
0

我認爲唯一的方法是迭代所有程序集中的所有類,這可能會很慢。

這裏是如何MVC asp.net搜索項目中的所有控制器:

private static List<Type> GetAllControllerTypes(IBuildManager buildManager) { 
     // Go through all assemblies referenced by the application and search for 
     // controllers and controller factories. 
     List<Type> controllerTypes = new List<Type>(); 
     ICollection assemblies = buildManager.GetReferencedAssemblies(); 
     foreach (Assembly assembly in assemblies) { 
      Type[] typesInAsm; 
      try { 
       typesInAsm = assembly.GetTypes(); 
      } 
      catch (ReflectionTypeLoadException ex) { 
       typesInAsm = ex.Types; 
      } 
      controllerTypes.AddRange(typesInAsm.Where(IsControllerType)); 
     } 
     return controllerTypes; 
    } 

在你的情況,你可以將代碼返工類似的東西:

private static List<Type> GetAllSubtypesOf(Type anInterface) { 
     List<Type> types = new List<Type>(); 
     ICollection assemblies = buildManager.GetReferencedAssemblies(); 
     foreach (Assembly assembly in assemblies) { 
      Type[] typesInAsm; 
      try { 
       typesInAsm = assembly.GetTypes(); 
      } 
      catch (ReflectionTypeLoadException ex) { 
       typesInAsm = ex.Types; 
      } 
      types.AddRange(typesInAsm.Where(t => anInterface.IsAssignableFrom(t))); 
     } 
     return types; 
    } 

注意,因爲遍歷所有程序集都是非常低效的asp.net MVC做一次並緩存結果。

+0

我不需要遍歷域中的所有類型。我已經有了潛在的類型。 – 2009-10-19 20:54:38