使用类型变量强制转换
下面的代码将不起作用,我想知道如何动态地将实例转换为在运行时确定的类型?使用类型变量强制转换
Convert.ChangeType()返回一个仍然需要转换的对象。因此,所有尝试调用()GetConstructor()或Activator.CreateInstance(),见下文。在某些时候,我需要明确地投入代码,我希望避免它或尽可能地推出它。
Type type = Type.GetType ("RandomChildClass");
Object obj = Activator.CreateInstance (type, new Object[]{ "argument" });
var instance = (type)obj;
我知道我可以创建接受< T>的方法,但我仍然不知道如何与动态随机型 Casting a variable using a Type variable
这是不可能使用Type
值确定类型的表达式的。 (因为它们被编入的类型系统泛型类型参数比的值不同。)
的变量的值是从代码执行运行时间,而表达类型是编译时构造。不用说,编译发生在代码运行之前,因此使用变量进行转换是不可能的。
Reflection(albiet笨重)或dynamic
(其基本上是比较容易使用的反射)允许调用任意方法或访问属性/对一个通用类型的对象表达字段 - 这是偶尔refered为“后期绑定” 。但是,调用操作的表达式的类型仍然是对象。
Interfaces可用于统一不同的类实现以进行正确的静态类型。然后新创建的对象可以转换为适用的接口(S)是必需的。就像其他表达式一样,这个类型是编译时间构造(因此必须直接指定该接口),但是代码现在不受特定类的限制。
如果创建一个系统以便这些“动态类”直接用于静态类型(C#)代码,并且可以保证接口或将其限制为一个小集合,那么使用接口可能是最干净的方法:例如var myAction = (IMyAction)obj
。否则,回到动态访问 - 直接或在幕后。
我的希望是动态地填充演员阵容中的((IMYACTION))部分,但从你的解释来看,它完全不可能出现。那是对的吗? – user2994682
做了一些更新以上澄清。 – user2994682
@ user2994682这是正确的。这是不可能的,出于同样的原因。 – user2864740
定义您的变量调用它的同样的问题作为dynamic
,它应该工作,我的意思是你仍然可以不投,但你可以访问你的方法:
dynamic obj = Activator.CreateInstance (type, new Object[]{ "argument" });
例如:
是否有可能不使用动态?我收到编译错误 – user2994682
作了一些更新以上澄清。 – user2994682
根据您的评论,您正在尝试将其添加到List<SomeDynamicClass>
。我的第一个想法是,如果你不能静态访问SomeDynamicClass
,那么我很好奇你是怎么做的,或者为什么你有一个List<SomeDynamicClass>
。这听起来像代码会好得多List<object>
或List<dynamic>
而不是。
如果你被限制为List<SomeDynamicClass>
那么它听起来像你应该直接跳到使用反射来调用Add
方法
var listType = theList.GetType();
var method = listType.GetMethod("Add");
method.Invoke(theList, obj);
我很抱歉产生困惑,我真的只想要一种动态投射到特定的孩子班的方式。之后发生了一个简单的添加基地名单将工作。 – user2994682
如果我构造一个子对象(通过调用构造函数)并将其转换为父对象,稍后当我想使用它时,我仍然需要将其明确地转换为子对象。但是如果我能够保持它的类型,将它添加到基类的列表中,在使用中它仍然保留它自己的类型(而不是基类),我在这个假设中错了吗? – user2994682
做了一些更新以上澄清。 – user2994682
如果以静态知道基类的类型,强制转换为该类型。例如:
void AddToList(List<Control> list, string typeName) {
var control = (Control)Activator.CreateInstance(typeName);
list.Add(control);
}
然后
var list = new List<Control>();
AddToList(list, "Button"):
AddToList(list, "Label"):
AddToList(list, "ListBox"):
如果需要以后做一些类型特异性,可以测试的类型和投:
foreach (Control child in list)
DoSomethingWithThe(control);
void DoSomethingWithThe(Control control)
{
Button button = control as Button;
if (button != null)
{
button.Click += Button_Click;
return;
}
Label label = control as Label;
if (label != null)
{
label.MouseOver += Label_MouseOver;
return;
}
//... etc.
}
或者使用OfType方法:
foreach (Button button in list.OfType<Button>())
button.Click += Button_Click;
foreach (Label label in list.OfType<Label>())
label.MouseOver += Label_MouseOver;
您还可以使用反映离子,但这相当麻烦,所以我不会举一个例子。如果您有一个与在基类型的不同子类型上定义的名称相同的属性,但不在基类型上,则反射会很有用。如果有许多子类型,类型检查会变得麻烦,所以反射可能是更好的方法。
谢谢,我想尽量保持孩子的类型。可能吗? – user2994682
做了一些更新以上澄清。 – user2994682
@ user2994682在user2864740回答时,不,在编译时不可能保留子的静态类型。但是,子对象始终保持其运行时间。例如,这段代码产生一个包含一个字符串和一个盒装int的列表:var objects = new List
你在施放后想用'instance'做什么? – JaredPar
只是将其添加到基类型列表 – user2994682