跨不同程序集版本传递类对象

发布于 2024-12-27 06:21:45 字数 1295 浏览 1 评论 0原文

场景是这样的 -

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

公共无效MyMethod(IMyInterface对象){}

  • 现在,在我的项目中,我创建了一个与“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 来动态创建您自己的类。但是,我们只能在动态生成的程序集中使用它,而不能在现有程序集中创建动态方法或类。

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

The scenario goes like this -

  • I have an assembly say 'MyAssembly'. An interface say 'IMyInterface' is defined in this assembly.
  • In the same assembly i have one class(MyClass) with a method define in it as :

public void MyMethod( IMyInterface object ) { }

  • Now in my project, i have created an interface with the same name and exact properties as exposed by the interface "IMyInterface" in 'MyAssembly'.
  • I have a class which extends this interface(the one which i have created in my project) and i want to pass the object of that class as a parameter to the method "MyMethod" in different assembly using reflection.

Issue is -

  • When i try to invoke the method using reflection, i got this exception that "Cannot convert object to type IMyInterface".

Code -

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

If, i am getting it right, this is because object created is in different assembly and the parameter expected by the method is of its own assembly.

Another approach i thought of was to create my own dynamic method in the class which will accept the object of my class.

I have tried to google for and come across through Reflection.Emit or RunSharp to dynamically create your own class. But, we can use this only in our dynamically generated Assemblies but can't create dynamic methods or class in already existing assembly.

I know generating assemblies at runtime is ain't good approach. But i can't think of anything now. Thanks for any help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

爱情眠于流年 2025-01-03 06:21:45

您正在与一种称为“类型标识”的东西作斗争,这是 .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 并实现“嵌入互操作类型”功能。没有什么适用于你的情况。

You are battling something called "Type identity", a very important DLL Hell counter-measure in the .NET framework. A type isn't just identified by its namespace name and type name, it also includes attributes of the assembly from which it came from. Specifically the assembly display name, [AssemblyVersion], [AssemblyCulture], PublicKeyToken and (indirectly) ProcessorArchitecture. You can see the 'real' type name with the Type.AssemblyQualifiedName property. The System.String class for example is System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089

This stops you from faking a type in another assembly unless you can give that assembly the exact same attributes. Much easier is to simply use the existing assembly, should be no problem in your case since you only use an interface.

Notably is that this requirement was relaxed somewhat in .NET 4. Types that were auto-generated from a COM type library are equivalent if their name and [Guid] matches. Which helped eliminate PIAs and implement the "Embed interop types" feature. Nothing that applies in your case.

紫瑟鸿黎 2025-01-03 06:21:45

这里:

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

问题就在那里;声明一个类似名称的接口是不够的。类型的范围由其程序集决定;也就是说,对于CLR来说,是一个完全不同的接口。

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

Here:

Now in my project, i have created an interface with the same name and exact properties as exposed by the interface "IMyInterface" in 'MyAssembly'.

There-in is the problem; it is not enough to declare a like-named interface. Types are scoped by their assembly; that is, to the CLR, a completely different interface.

Instead, add a reference to the original assembly, and implement the interface that is already defined. It should only be defined once.

固执像三岁 2025-01-03 06:21:45

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

创建并构建 MyInterfaces dll:

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

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

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”中定义的相同接口。

If I understand your problem correctly, I believe you want to define your Interfaces in their own assembly, then reference the common interfaces assembly from within each of the other two. That way, each assembly is referencing the SAME Interface definition:

Create and build the MyInterfaces dll:

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

Then create your first assembly in a different project, and set a reference to the dll created for MyInterfaces. Create your class, noting the "using" statements at the top of the module:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MyInterfaces;

namespace MyFirstProject
{
    public class MyClass1
    {
        public void MyMethod(IMyInterface SomeObject) { }
    }
}

Now, I believe your dynamic object creation should work, since both objects implement the same interface defined in "MyInterfaces".

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文