2011-08-25 67 views
2

我處於這種情況,我必須在簽名的應用程序中使用未簽名的第三方.NET DLL。所以我決定在運行時動態地加載該庫:在動態加載的第三方程序集中使用靜態類

var asm = Assembly.LoadFrom("THIRDPARTYASSEMBLY.DLL"); 

有一個在我定義的接口在我的應用程序的DLL靜態類和使用GetUninitializedObject()加載類:

var obj = FormatterServices.GetUninitializedObject(asm.GetType("NAMESPACE.CLASS")) as IMyInterface; 

雖然我試圖加載類不是抽象的(這是一個public static類),我在運行時出現此錯誤:

System.MemberAccessException是未處理的:不能ç創建一個抽象類 。

很明顯,我不能使用CreateInstance方法,因爲靜態類沒有任何構造函數。

那麼你會建議什麼?我想要:

  • 從該庫調用public static方法。 (我目前使用InvokeMember()。)
  • 獲取Custom Type屬性。
  • 在我的應用程序中處理幾個Custom Events

在此先感謝。

回答

5

而不是嘗試動態調用該方法,您可以嘗試強名稱的第三方DLL。

您將需要一個密鑰來強烈地命名dll。你可以使用你已經用於你自己的DLL的一個,或者爲此創建一個新的(使用sn -k)。

爲強名稱已編譯的程序集:

  1. 打開Visual Studio命令提示符(獲取工具集成到你的路徑)。
  2. 從組件生成IL:
    ildasm ThirdParty.dll /out:ThirdParty.il
  3. 原ThirdParty.dll重命名爲別的東西。
  4. 生成一個新的DLL,強命名它爲你這樣做:
    ilasm ThirdParty.il /dll /key=MyKey.snk

這將導致一個新的ThirdParty.dll這將是強勁,已指定的鍵命名。然後,您可以添加一個直接引用,並像通常那樣直接調用這些方法。

+0

第4步有一個錯字:應該是'ilasm ThirdParty.il/dll /key=MyKey.snk'謝謝你的回答:) –

+0

@John:謝謝,糾正。 – adrianbanks

4

如果它只是一個靜態類,則不需要未初始化的對象。一旦你得到的類型,例如

Type t = asm.GetType("NAMESPACE.CLASS"); 

你可以得到你需要

MethodInfo method = t.GetMethod("MethodName"); 
//getmethod has some useful overloads 
//also GetMethods() returns a MethodInfo[] array containing all methods 

,那麼你可以調用

object result = method.Invoke(null, new object[] { param1, param2, ... }); 

有這樣做,以及其他的方式方法。您可以使用委託來獲取指向該方法的函數指針,而不是調用invoke。

我不確定如何做事件處理程序,雖然我確定如果您在Type對象下瀏覽intellisense,您應該能夠找到某些東西。就屬性而言,通常只使用它們作爲對象,但如果要使用靜態類的屬性,並且事先已知道返回類型,則可以創建一個類來處理它:

public class ExternalProperty<PropertyType> 
{ 
    delegate PropertyType GetFunction(); 
    delegate void SetFunction(PropertyType value); 
    GetFunction GetValue; 
    SetFunction SetValue; 

    public ExternalProperty(PropertyInfo externalProperty) 
    { 
     MethodInfo getMethod = externalProperty.GetGetMethod(); 
     GetFunction getter = (GetFunction)Delegate.CreateDelegate(typeof(GetFunction), getMethod); 
     MethodInfo setMethod = externalProperty.GetSetMethod(); 
     SetFunction setter = (SetFunction)Delegate.CreateDelegate(typeof(SetFunction), setMethod); 
    } 

    public PropertyType Value 
    { 
     get { return GetValue(); } 
     set 
     { 
      SetValue(value); 
     } 
    } 
} 

如果你已經知道屬性類型,使用這個類很容易。假設你有一個字符串類型的屬性名稱:

ExternalProperty<string> PropName = new ExternalProperty(t.GetProperty("Name")); 
string oldName = PropName.Value; //this will call the property's getter 
PropName.Value = "new name"; //this will call the property's setter 

它沒有錯誤檢查,但這樣,如果你嘗試通過比指定,或一個不同類型的屬性,無法找到它,它會打破。這也不適用於對象,只適用於靜態類。希望有所幫助。

+0

沒錯。而'GetUnitializedObject' *實例化類,所以它當然不能用於與靜態類進行交互。 –

+0

我目前使用類似的方法來調用方法,但我無法使用'GetProperty()'獲取屬性,並將它們轉換爲我的應用程序中的類似匹配接口。另外我不知道如何設置事件處理程序。 – fardjad