在动态加载的第三方程序集中使用静态类

far*_*jad 2 .net c# reflection dll static

我遇到的情况是我必须在签名的应用程序中使用未签名的第三方.NET DLL.所以我决定在运行时动态加载该库:

var asm = Assembly.LoadFrom("THIRDPARTYASSEMBLY.DLL");
Run Code Online (Sandbox Code Playgroud)

DLL中有一个静态类,我在我的应用程序中定义了一个接口,用于GetUninitializedObject()加载类:

var obj = FormatterServices.GetUninitializedObject(asm.GetType("NAMESPACE.CLASS")) as IMyInterface;
Run Code Online (Sandbox Code Playgroud)

虽然我试图加载的类不是抽象的(它是一个public static类)我在运行时遇到这个错误:

System.MemberAccessException未处理:无法创建抽象类.

显然我不能使用CreateInstance方法,因为静态类没有任何构造函数.

那么你会建议什么?我想要:

  • public static从该库调用方法.(我现在正在使用InvokeMember().)
  • 获得一处Custom Type房产.
  • Custom Events在我的应用程序中处理一些.

提前致谢.

Hyp*_*oad 5

如果它只是一个静态类,则不需要未初始化的对象。一旦你得到了类型,例如

Type t = asm.GetType("NAMESPACE.CLASS");
Run Code Online (Sandbox Code Playgroud)

你可以得到你需要的方法

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

然后你可以打电话

object result = method.Invoke(null, new object[] { param1, param2, ... } );
Run Code Online (Sandbox Code Playgroud)

还有其他方法可以做到这一点。您可以使用委托来获取指向该方法的函数指针,而不是调用 invoke。

我不确定如何处理事件处理程序,但我确定如果您在 Type 对象下浏览智能感知,您应该能够找到一些东西。就属性而言,一般只将它们用于对象,但是如果要在静态类上使用属性,并且事先已经知道返回类型,则可以创建一个类来处理它:

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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您已经知道属性类型,那么使用这个类非常容易。假设您有一个字符串类型的属性名称:

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
Run Code Online (Sandbox Code Playgroud)

它没有错误检查,因此如果您尝试传递与您指定的类型不同的属性,或者无法找到它的属性,它将中断。这也不适用于对象,仅适用于静态类。希望有帮助。


adr*_*nks 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使用您指定的键命名的new .然后,您可以添加对它的直接引用,并像平常一样直接调用方法.