【问题标题】:Working with static class in a dynamically loaded third party assembly在动态加载的第三方程序集中使用静态类
【发布时间】:2011-08-25 23:04:12
【问题描述】:

我的情况是我必须在我的签名应用程序中使用未签名的第三方 .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

提前致谢。

【问题讨论】:

    标签: c# .net reflection dll static


    【解决方案1】:

    您可以尝试强命名第三方 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,它将使用您指定的密钥进行强命名。然后,您可以添加对它的直接引用并像往常一样直接调用方法。

    【讨论】:

    • 您的第 4 步有一个错字:应该是 'ilasm ThirdParty.il /dll /key=MyKey.snk' 感谢您的回答 :)
    【解决方案2】:

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

    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, ... } );
    

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

    我不确定如何处理事件处理程序,但我确定如果您在 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);
            }
        }
    }
    

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

    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
    

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

    【讨论】:

    • 对。而GetUnitializedObject实例化类,所以当然不能用于与静态类交互。
    • 我目前正在使用类似的方法来调用方法,但我无法使用GetProperty() 获取属性并将它们转换为我的应用程序中类似的匹配接口。我也不知道如何设置事件处理程序。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多