2010-01-29 21 views
2

我想通過名稱(字符串)實例化一個類,而不指定命名空間或程序集。像這樣(Unity語法):找到類來實例化沒有命名空間或程序集的名稱? (.NET)

var processor = container.Resolve<IProcessor>("SpecialProcessor"); 

會實例化它發現的第一個IP處理器,稱爲SpecialProcessor。也許

MyNamespace.SpecialProcessor 

我想避免必須在配置中創建一個條目,每次有人添加一個新的處理器。儘管有所有候選人集合的條目,但我很好。

我可以使用IoC容器來做這種事情嗎?還是應該自己推出?

+0

我會評論這個,因爲它不是一個直接回答你的問題,但你很可能腳本的條目到配置,通過構建腳本(S),所以你建立你一定要一次比一次容器配置中列出的所有IP處理器。 – Jay 2010-01-29 04:33:57

回答

1

這裏有一個功能,可以做一些與你想要的東西非常相似的東西。你可以修改它來很容易地基於特定的類名進行過濾。

這些函數引用了我們用於日誌記錄和異常處理的一些實用程序。您需要將其替換爲通常在這些情況下執行的任何操作。

public static T FindAndCreate<T>(bool localOnly, bool exportedOnly) 
    { 
     Type[] types = FindAssignableClasses(typeof(T), localOnly, exportedOnly, false); 
     if (types.Length == 0) 
     { 
      return default(T); 
     } 
     if (types.Length != 1) 
     { 
      Log.Warn(typeof(ReflectionUtil), 
        "FindAndCreate found {0} instances of {1} whereas only 1 was expected. Using {2}. {3}", 
        types.Length, 
        typeof(T).FullName, 
        types[0].FullName, 
        String.Join("\r\n ", Array.ConvertAll<Type, String>(types, GetFullName))); 
     } 
     try 
     { 
      return (T)Activator.CreateInstance(types[0]); 
     } 
     catch (Exception ex) 
     { 
      throw ExceptionUtil.Rethrow(ex, 
             "Unable to create instance of {0} found for interface {1}.", 
             types[0].FullName, 
             typeof(T).FullName); 
     } 
    } 

    public static Type[] FindAssignableClasses(Type assignable, bool localOnly, bool exportedOnly, bool loadDll) 
    { 
     var list = new List<Type>(); 
     string localDirectoryName = Path.GetDirectoryName(typeof(ReflectionUtil).Assembly.CodeBase); 

     if (loadDll && !_loadedAllDlls) 
     { 
      foreach (string dllPath in Directory.GetFiles(localDirectoryName.Substring(6), "*.dll")) 
      { 
       try 
       { 
        Assembly.LoadFrom(dllPath); 
       } 
       catch 
       { 
        // ignore 
       } 
      } 
      _loadedAllDlls = true; 
     } 

     foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies()) 
     { 
      try 
      { 
       if (localOnly && Path.GetDirectoryName(asm.CodeBase) != localDirectoryName) 
       { 
        continue; 
       } 

       Type[] typesInAssembly; 
       try 
       { 
        typesInAssembly = exportedOnly ? asm.GetExportedTypes() : asm.GetTypes(); 
       } 
       catch 
       { 
        continue; 
       } 

       foreach (Type t in typesInAssembly) 
       { 
        try 
        { 
         if (assignable.IsAssignableFrom(t) && assignable != t) 
         { 
          list.Add(t); 
         } 
        } 
        catch (Exception ex) 
        { 
         Log.Debug(
          typeof(ReflectionUtil), 
          String.Format(
           "Error searching for types assignable to type {0} searching assembly {1} testing {2}{3}", 
           assignable.FullName, 
           asm.FullName, 
           t.FullName, 
           FlattenReflectionTypeLoadException(ex)), 
          ex); 
        } 
       } 
      } 
      catch (Exception ex) 
      { 
       // ignore dynamic module error, no way to check for this condition first 
       // http://groups.google.com/group/microsoft.public.dotnet.languages.csharp/browse_thread/thread/7b02223aefc6afba/c8f5bd05cc8b24b0 
       if (!(ex is NotSupportedException && ex.Message.Contains("not supported in a dynamic"))) 
       { 
        Log.Debug(
         typeof(ReflectionUtil), 
         String.Format(
          "Error searching for types assignable to type {0} searching assembly {1} from {2}{3}", 
          assignable.FullName, 
          asm.FullName, 
          asm.CodeBase, 
          FlattenReflectionTypeLoadException(ex)), 
         ex); 
       } 
      } 
     } 

     return list.ToArray(); 
    } 
+0

謝謝。這是一些方便的代碼。在我製作我的作品時,我會從這裏採取一些想法。 – 2010-01-29 18:15:19

+0

@BT:如果它適合你,請確定並接受它作爲你的答案。 ;) – IAbstract 2010-01-31 05:59:26

+0

@Sam:這是很好看的東西。我必須記住自己。 – IAbstract 2010-01-31 06:01:36

0

聽起來好像你有一個插件架構,你想讓其他組件不需要更新一些主配置文件就可以提供IProcessor的實現。如果是這樣的話,那麼我認爲你最適合使用MEF(託管擴展性框架)(Website)。

這是一個旨在允許這種行爲的框架。一旦你建立一個目錄組件從,進口IProcessor實例集合加載組件是一樣容易以下

var processors = container.GetExportedValues<IProcessor>(); 

有很多教程在線MEF應該讓你開始。

+0

是的,你說得對。但這是我需要MEF的唯一的東西,它是應用程序的一小部分。我想我現在只會推出自己的產品。我也想通過名稱空間來限制它,就像只允許「Namespace。*」匹配。這就像策略注入塊一樣,但是工作方式相反(將匹配規則應用於傳入的類型,而不是匹配的類型)。 – 2010-01-29 18:12:34

相關問題