我希望有两个答案中的一个,要么不可能,要么非常简单,我忽略了明显的Google查询。
潜在的问题是我有一个通用对象通过EventHandler
传入,该对象将对象装箱并模糊真实类型;只有在运行时我才知道对象是什么。
不可否认,dynamic
关键字可以解决问题,但我希望不会丢失IntelliSense以及所有内容,如果我可以避免它。另外,如果没有大量反射,它无法解决不知道通用对象的每个属性的问题。
编辑:我们的想法是能够确定方法参数中对象的真实类型,然后在不事先知道的情况下将该对象转换为真实类型。这只是一个简化的例子。盒装可能是错误的术语。
一个例子:
public class Program
{
static void Main(string[] args)
{
var container = new Container<Containee>(
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<T>
{
public Container(T entity)
{
Entity = entity;
}
public T Entity { get; internal set; }
}
显然,这不会编译,因为没有真正的方法可以作为变量进行转换。但是,我希望有一种方法可以获得对实际对象和类型的引用,或者至少是一种动态重新创建类型的方法。
我希望有一些简单的东西我可以忽略,或者更好的解决方法。关键是能够将任何对象包装在容器中,并稍后弄清楚它是什么。
答案 0 :(得分:8)
我们的想法是能够确定方法参数
中对象的真实类型
这很容易(你已经在做了)。
Type actualType = param.GetType();
这将为您提供对象的实际具体类型
然后将该对象转换为真正的类型
这是事情发生的地方。 C#中的转换操作符(其用法是人们称之为“转换”)可以做两件事:
在您的情况下,第一个选项是正确的;与所有运算符一样,转换运算符不是多态的。也就是说,只有在被引用的类型上定义了运算符,而不是被引用的对象时才应用运算符。如果您想进一步澄清这一点,请告诉我,但我不认为这与您的问题密切相关,所以除非被问到,否则我不打算进一步澄清。
第二个选项是唯一可以实际应用于您的选项,但请考虑您希望执行此操作的唯一两个原因:
object
,因此它几乎与它一样高)(绝大多数演员出于理由#1)
您希望使用其中任何一个选项的原因是,您可以拥有强类型对象并使用在该类型上定义的各种成员。但是,所有这些内容仅适用于您在编写代码时知道的类型。强制转换为在编译时未知的类型是没有意义的,因为强制转换对实际对象没有任何作用(它是,并且将保留,它的真实类型;唯一改变的是类型用于引用对象的变量。
如果您可以提供一个进一步充实的示例,说明您实际上要做什么(完成代码,或者您希望或希望它能够工作),我可能能够提供更接近模仿的东西你想要什么,但正如我所描述的那样,这是我能得到的具体内容。
答案 1 :(得分:4)
首先:那不是“拳击”。拳击用于值类型,例如struct
s。
其次:您可能需要的是:
Reflection.Emit
。第三点:您的示例代码确实variable1 as variable2
,这实际上没有意义。 :\那你打算做什么?也许还有更好的方法。
答案 2 :(得分:1)
var actualType = boxed as originalType;
正好我们在同一页上,让我解释为什么这是不可能的。
var
是一个编译时构造。它与直接声明具有正确类型的变量相同。除了更容易键入外,它主要用于匿名类型,如暗示的那样,没有名称。
无论如何,为了解决您的问题,最好的办法是使用动态代码生成,Reflection.Emit
或CodeDom
(如果不这样做,后者会更容易理解知道ILASM,但要慢得多。)
根据你真正想做的事情,你可能会躲过像
这样的事情if(someObject is Container<Containee>) {
var container = (Container<Containee>)someObject;
//...
}
但是,如果你可以期待任何类型,那么......祝你好运。
答案 3 :(得分:1)
潜在的问题是我有一个 通过一个传入的通用对象 包装对象的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 ();
改写您的问题,并在完成'魔法铸造'之后,将您的样本扩展为您的工作方式。这会让我们知道你想要完成的任务。
答案 4 :(得分:1)
您可以使用dynamic
:
dynamic actualType = boxed;
actualType.Entity.Property2 = "But I like this better.";
这应该编译和工作。