2012-02-07 17 views
6

我正在嘗試使用AppDomain.AssemblyResolve事件處理異常,同時解析在運行時加載的某些dll的程序集(SerializationException for dynamically loaded Type)。使用AppDomain.AssemblyResolve事件

當事件被觸發,我加載在我的目錄中的所有DLL文件,並創建一個Assembly數組,然後我用這個方法來獲取Assembly包含I型註明:

public static Assembly GetAssemblyContainingType(String completeTypeName, Assembly[] assemblies) 
    { 
     Assembly assembly = null; 

     foreach (Assembly currentassembly in assemblies) 
     { 
      Type t = currentassembly.GetType(completeTypeName, false, true); 
      if (t != null) 
      { 
       assembly = currentassembly; 
       break; 
      } 
     } 

     return assembly; 
    } 

的問題是,這代碼僅適用於AssemblyQualifiedName,並且該事件提供的ResolveEventArgs.Name不太有用。

你能告訴我一些解決方法嗎?

當它被觸發時,是否有辦法將其他參數傳遞給事件?

回答

12

您可以定義組件的字典目錄,如:

private readonly IDictionary<string,Assembly> additional = 
    new Dictionary<string,Assembly>(); 

加載此字典,從已知的目錄組件,如:

foreach (var assemblyName ... corresponding to DLL names in your directory...) { 
    var assembly = Assembly.Load(assemblyName); 
    additional.Add(assembly.FullName, assembly); 
} 

提供實現爲鉤...

private Assembly ResolveAssembly(Object sender, ResolveEventArgs e) { 
    Assembly res; 
    additional.TryGetValue(e.Name, out res); 
    return res; 
} 

...並把它連接到事件:

AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += ResolveAssembly; 
AppDomain.CurrentDomain.AssemblyResolve += ResolveAssembly; 

這應該可以做到。

+5

不預加載程序集,不需要AssemblyResolve事件處理程序? – 2012-02-07 18:02:26

+2

@mikez據我所知,使用'Assembly.Load(assemblyName)'加載一個程序集不會自動使它可用於應用程序域的程序集解析代碼(除非該代碼可以使用默認分辨率訪問程序集處理)。這段代碼從工作系統中解除(我刪除了錯誤處理代碼,例如在'additional.TryGetValue(e.Name,out res)'調用周圍以簡化一些事情)。當我刪除'ResolveAssembly'鉤子時,我的工作系統停止工作:) – dasblinkenlight 2012-02-07 18:16:57

+2

當您構建字典時,請使用AssemblyName.GetAssemblyName()而不是Assmebly.Load將程序集名稱命名爲文件名映射並避免無條件加載所有的程序集。 – 2012-05-02 23:15:57

0

如果您知道可能包含類型的程序集列表,那麼您打算反序列化,在序列化之前簡單地預加載所有程序集可能會更好。

當AssemblyResolve事件被觸發時,您不知道引起加載的類型,但只有程序集名稱。目前還不清楚爲什麼你會在這種情況下查找某種特定類型的程序集。

請注意,如果2個程序集碰巧具有相同的標識(即非強簽名的情況下的文件名),並且一個已加載的事件即使在已裝入的程序集中未找到類型,也不會觸發。

鏈接到文章用於歷史的目的:Resolving Assembly Loads

+0

正如你也可以閱讀我的老問題http://stackoverflow.com/q/9158353/1061499我正在研究一個應用程序,它使用插件的方法在運行時加載接口的各種應用程序。當應用程序關閉時,我需要序列化這些對象,然後當應用程序重新啓動時,必須對這些對象進行反序列化。問題是對象類型在運行時被加載,所以它們的類型沒有被解析... – davioooh 2012-02-09 08:50:58