【问题标题】:Passing class objects across different assembly versions在不同的程序集版本之间传递类对象
【发布时间】:2012-02-10 20:48:31
【问题描述】:

剧情是这样的——

  • 我有一个程序集说“MyAssembly”。此程序集中定义了一个接口,例如“IMyInterface”。
  • 在同一个程序集中,我有一个类(MyClass),其中定义了一个方法:

public void MyMethod(IMyInterface object) { }

  • 现在在我的项目中,我创建了一个与“MyAssembly”中的接口“IMyInterface”公开的名称和属性完全相同的接口。
  • 我有一个扩展此接口的类(我在项目中创建的接口),我想将该类的对象作为参数传递给使用反射的不同程序集中的方法“MyMethod”。

问题是 -

  • 当我尝试使用反射调用该方法时,我得到了 “无法将对象转换为 IMyInterface 类型”的异常

代码 -

Assembly myAssembly = Assembly.LoadFrom("MyAssembly");
object classObject = myAssembly.CreateInstance("MyClass");
Type classType = myAssembly.GetType("MyClass");
MethodInfo myMethod = classType.GetMethod("MyMethod", BindingFlags.Instance);

// Creating an object of class in the latest assembly and need to pass this
// to method in assembly with different version.
ClassExtendingMyInterface obj= new ClassExtendingMyInterface ();

myMethod.Invoke(classObject, new object[] { obj});

如果我说对了,这是因为创建的对象在不同的​​程序集中,并且该方法期望的参数是它自己的程序集。

我想到的另一种方法是在类中创建自己的动态方法,该方法将接受我的类的对象。

我曾尝试在 Google 上搜索并通过 Reflection.EmitRunSharp 来动态创建您自己的课程。但是,我们只能在动态生成的程序集中使用它,而不能在现有程序集中创建动态方法或类。

我知道在运行时生成程序集不是一个好方法。但我现在什么都想不出来。感谢您的帮助。

【问题讨论】:

    标签: c# reflection assemblies reflection.emit reflector


    【解决方案1】:

    您正在与称为“类型标识”的东西作斗争,这是 .NET 框架中非常重要的 DLL Hell 对策。类型不仅由其命名空间名称和类型名称标识,它还包括它所来自的程序集的属性。特别是程序集显示名称、[AssemblyVersion]、[AssemblyCulture]、PublicKeyToken 和(间接)ProcessorArchitecture。您可以使用 Type.AssemblyQualifiedName 属性查看“真实”类型名称。 System.String 类例如是System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089

    这会阻止您在另一个程序集中伪造一个类型,除非您可以为该程序集赋予完全相同的属性。简单地使用现有的程序集要容易得多,因为您只使用一个接口,所以在您的情况下应该没问题。

    值得注意的是,该要求在 .NET 4 中有所放宽。从 COM 类型库自动生成的类型如果其名称和 [Guid] 匹配,则它们是等效的。这有助于消除 PIA 并实现“嵌入互操作类型”功能。不适用于您的情况。

    【讨论】:

    • >更容易的是简单地使用现有的程序集,在你的情况下应该没问题,因为你只使用一个接口。但我想要我自己的实现(实现接口的方式)并希望传递该对象。但是自从那个实现以来,我不能在现有的程序集中拥有,因为它已经被部署了。无法修改该程序集:(这就是为什么我试图在较新版本的程序集中实现它并通过反射将其作为参数传递。如果您能提供帮助,我可以通过其他方式实现这一点..谢谢.. :)跨度>
    • 我不明白为什么会出现问题,只需使用已部署程序集的副本并将其添加为项目的引用即可。无需反射黑客。
    • 我无法添加对程序集的引用,因为我需要根据某些用例在运行时加载程序集.. 我必须根据一些用户场景加载程序集.. :(
    • 它已经以这种方式工作,只有在您执行使用其中类型的代码时才会加载程序集。无需反射黑客。
    • 抱歉没能找到你。如何将我的接口实现注入其他程序集?
    【解决方案2】:

    这里:

    现在在我的项目中,我创建了一个与“MyAssembly”中的接口“IMyInterface”公开的名称和属性相同的接口。

    有问题;声明一个同名接口是不够的。类型由它们的程序集限定;也就是说,对于 CLR 来说,是一个完全不同的接口。

    改为向原始程序集添加引用,并实现已定义的接口。它应该只定义一次。

    【讨论】:

    • 我无法添加对程序集的引用,因为我需要根据某些用例在运行时加载程序集.. :(
    【解决方案3】:

    如果我正确理解您的问题,我相信您想在自己的程序集中定义您的接口,然后从其他两个程序集中引用通用接口程序集。这样,每个程序集都引用了 SAME 接口定义:

    创建和构建 MyInterfaces dll:

    namespace MyInterfaces
    {
        public interface IMyInterface
        {
            void SharedMethod();
        }
    }
    

    然后在另一个项目中创建您的第一个程序集,并设置对为 MyInterfaces 创建的 dll 的引用。创建你的类,注意模块顶部的“使用”语句:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using MyInterfaces;
    
    namespace MyFirstProject
    {
        public class MyClass1
        {
            public void MyMethod(IMyInterface SomeObject) { }
        }
    }
    

    现在,我相信您的动态对象创建应该可以工作,因为两个对象都实现了在“MyInterfaces”中定义的相同接口。

    【讨论】:

      猜你喜欢
      • 2020-07-22
      • 1970-01-01
      • 2021-12-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多