将盒装对象转换回原始类型

我希望有两个答案中的一个,要么不可能,要么非常简单,我忽略了明显的Google查询。

潜在的问题是我有一个通用对象通过EventHandler传入,它装入对象并模糊真实类型; 只有在运行时我才知道对象是什么。

不可否认, dynamic关键字可以解决这个问题,但我想不要失去智能感知,如果我可以避免它。 另外,它没有解决不知道通用对象的每个属性没有大量reflection的情况。

编辑:我们的想法是能够确定方法参数中对象的真实类型,然后在不事先知道的情况下将该对象转换为真实类型。 这只是一个简化的例子。 盒装可能是错误的术语。

一个例子:

 public class Program { static void Main(string[] args) { var container = new Container( new Containee { Property1 = Guid.NewGuid(), Property2 = "I'm a property!", Property3 = DateTime.Now } ); var boxed = (object)container; var originalType = boxed.GetType(); // DOES NOT COMPILE: would like an operation like this // EDIT: Request for more detail var actualType = boxed as originalType; actualType.Entity.Property2 = "But I like this better."; } } public class Containee { public Guid Property1 { get; set; } public string Property2 { get; set; } public DateTime Property3 { get; set; } } public class Container { public Container(T entity) { Entity = entity; } public T Entity { get; internal set; } } 

很明显,这将无法编译,因为没有真正的方法可以作为变量进行转换。 但是,我希望有一种方法可以获得对实际对象和类型的引用,或者至少是一种动态重新创建类型的方法。

我希望有一些简单的东西我可以忽略,或者更好的解决方法。 关键是能够将任何对象包装在容器中,并稍后弄清楚它是什么。

我们的想法是能够确定方法参数中对象的真实类型

这很容易(你已经在做了)。

 Type actualType = param.GetType(); 

这将为您提供对象的实际具体类型

然后将该对象转换为真正的类型

这是事情有点落空的地方。 C#中的转换操作符(其用法是人们称之为“转换”)可以做两件事:

  1. 通过将转换应用于现有对象,使用特定于类型的显式转换来创建新对象(请注意,这是创建的引用;原始对象的类型永远不会更改)
  2. 允许开发人员将对象引用为其inheritance层次结构中与当前提供的类型不同的类型(或者在层次结构中比当前引用的类型更低的类型上实现的接口)

在你的情况下,第一个选择是正确的; 与所有运算符一样,转换运算符不是多态的。 也就是说,只有在被引用的类型上定义运算符时才应用运算符,而不是被引用的对象 。 如果您想进一步澄清这一点,请告诉我,但我不认为这与您的问题密切相关,所以除非被问到,否则我不会进一步深入讨论。

第二个选项是唯一可以实际应用于您的选项,但请考虑您希望执行此操作的唯一两个原因:

  1. 因此,您可以将对象称为特定的具体类型,其级别低于当前提供的级别(在您的情况下,您的对象是一个object ,因此它几乎与它一样高)
  2. 这样您就可以将对象称为层次结构中较高的类型,以便绕过隐藏(但不会被覆盖)的成员。

(绝大多数演员是出于理由#1)

您希望使用这些选项中的任何一个的原因是,您可以拥有强类型对象并使用在该类型上定义的各种成员。 但是所有这些东西只适用于编写代码时所知道的类型。 在编译时强制转换为未知的类型是没有意义的,因为强制转换对实际对象没有任何作用(它是,并且将保留,它的真实类型;唯一改变的是类型引用对象的变量 )。

如果你可以提供一个进一步充实的例子来说明你实际上要做的事情(完成代码,你要么喜欢或期望它可以工作),我可能能够提供一些模仿你的东西更接近你的东西想要,但正如我所描述的那样,这是我能得到的具体。

首先:那不是“拳击”。 拳击是用于值类型,如struct

第二个:你可能需要的是:

  • 编译时reflection,C#没有
  • 动态代码生成,您可以使用Reflection.Emit (痛苦地)执行此操作。

第三,你的示例代码将variable1 as variable2 ,这实际上没有意义。 :\那你打算做什么? 也许有更好的方法。

 var actualType = boxed as originalType; 

就这样,我们在同一页上,让我解释为什么这是不可能的。

var是一个编译时构造。 它与直接声明具有正确类型的变量相同。 除了更容易键入外,它的主要用途是匿名类型,如暗示的那样,没有名称。

无论如何,为了解决你的问题,你最好的选择是使用Dynamic.Emit或CodeDom动态代码生成(如果你不了解ILASM,后者更容易理解,但速度要慢得多)。

根据你真正想做的事情,你可能会得到类似的东西

 if(someObject is Container) { var container = (Container)someObject; //... } 

但是,如果你可以期待任何类型,那么……祝你好运。

潜在的问题是我有一个通用对象通过EventHandler传入,它装入对象并模糊真实类型; 只有在运行时我才知道对象是什么。

如果仅在运行时知道类型,您希望如何处理它? 您无法调用任何特定的类方法,因为您无论如何都不会知道确切的类型,除非所有对象共享一组可以作为接口提取的方法。

基本上,您有几种选择:

  • 使用is针对不同类型做不同的事情:

     object value = GetValue (); if (value is Program) ((Program)value).Run (); else if (value is Animal) ((Animal)value).Run (); 
  • 如果所有可能的类型都应该共享一组操作,请使用接口:

     object value = GetValue (); IRunnable runnable = (IRunnable)value; runnable.Run (); 
  • 在完成“魔法铸造”之后,重新解释您的问题并扩展您的样本,看看它是如何工作的。 这会让我们知道你想要完成什么。

你可以使用dynamic

 dynamic actualType = boxed; actualType.Entity.Property2 = "But I like this better."; 

这应该编译和工作。