2010-05-11 89 views
2

有没有办法在不同类型的不同组件之间进行强制转换?我需要执行一个函数,它的程序集已经加载了Assembly.Load(ReadAllBytes(...)),但是它在参数投射中失败了。那么,有没有什么办法可以在c#中“reinterpret_cast”对象?强制铸造一种组装类型到另一种组装类型在c#

编辑我铸钢问题的

最基本的例子是:

Assembly ass = Assembly.Load(File.ReadAllBytes("external.dll")) 
object other_type_instance = ass.GetType("OtherType").InvokeMember(null, BindingFlags.CreateInstance, null, null, new Object[]{}); 
OtherType casted_isntance = (OtherType)other_type_instance; // fails with runtime error, because there are two OtherType:s classes loaded. 
+0

请提供一些代码 – 2010-05-11 21:12:35

+0

我认为你会更乐意编写一个适配器类来包装一种类型并提供与另一种类型兼容的接口。当然,如果其他类型是密封的或其他不可变的,那么你很大程度上没有运气。 – 2010-12-10 19:49:19

回答

5

除非两种类型共享继承关系,一个通用的接口,或类型之一提供了一个转换操作符到另一个...不。

如果您需要更具体的建议,您将不得不提供一些额外的详细信息,但这里是C#中铸造行为的一般概要。

在C#铸造可以是表示保留操作或表示改变之一。当您将实例强制转换为更宽或更窄的类型时,它将继承heirarchy或其实现的接口,您将执行保留转换的表示。您仍然在处理相同的位,编译器/运行时只需确保您指定的类型对于正在处理的对象的实例有效。跨继承heirarchies或未实现实例的接口是非法的。

对于自定义类型,表示变化转换是从现有类型创建新实例的转换。您可以定义自己的类型转换操作符的类型:

public class MyType 
{ 
    public static int implicit operator int(MyType t) 
    { 
     return 42; // trivial conversion example 
    } 
} 

Conversion operators可以被定义为implicitexplicit - 它决定了编译器是否会选择申请他们为你(隐含的)或将rquire你明确地投当你想要一个收敛(明确)的类型。

鉴于您所描述的内容,您可能需要编写一个实用类来执行从一种类型到另一种类型的转换。不幸的是,C#或.NET中没有任何内容可以为您做到这一点。

+0

我不认为这是OP的要求。这个问题有点神秘,但我的理解是,由于重新加载了一个Assembly,他有两个不同的类型标记用于加载相同的类。这会导致有趣的异常,如'someValue'(Intellisense显示的类型为OtherType)'不是OtherType'类型。这种情况下的“转换”实际上更类似于马沙林。 – 2010-05-11 22:31:25

2

如果您有两个不同版本的程序集加载并且两个类是兼容的(相同版本的程序集或对特定类没有更改),则一种选择是从一个实例序列化到内存并反序列化为实例在你需要的装配中。如果由于新程序集中的更改而导致类之间可能存在差异,则需要考虑更多常见的序列化问题。如果是这样的话,我建议看看DataContractSerializer,它可以支持更复杂的场景。

+1

http://blogs.msdn.com/suzcook/archive/2003/05/29/57143.aspx可能会有所帮助。 – user7116 2010-05-12 00:33:05

0

最后通过使用DynamicMethod,Emit-namespace和MethodUtil.ReplaceMethod(从http://www.codeproject.com/KB/dotnet/CLRMethodInjection.aspx)的组合,在不兼容的类型之间进行投射。很难说哪些是必要的,如果你有兴趣只在铸造这是可选的...我只是很高兴外部功能invokation工作,即使它的参数是从不同的组件......

+1

有趣,但也非常可怕。 – 2010-05-12 23:26:43

0

C#许可证不确定的输入,比如var和object,但这两者在行为上是完全不同的。例如,假设您已经序列化了一个类或结构体,并且不能将其强制转换为在Array.Copy方法中使用。一种解决方法是返回到您的类或结构实例化,并将其转换为“对象”。这样编译器将允许你在必要时将它投射到任何地方。

当然,您将失去该类型安全性的保护,但对于小部分代码而言,与编写整个铸造方法相比,这将是更易于管理的解决方案。