使用Type变量强制转换

时间:2014-01-25 02:24:12

标签: c# casting activator

下面的代码不起作用,我想知道如何动态地将实例转换为在运行时确定的类型?

Convert.ChangeType()返回仍需要强制转换的Object。所有尝试Invoke()的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

4 个答案:

答案 0 :(得分:4)

无法使用Type 来确定表达式的类型。 (泛型类型参数与值不同,因为它们被编入类型系统。)

变量的值来自运行时代码执行,而表达式类型是编译时构造。毋庸置疑,编译发生在代码运行之前,因此使用变量进行强制转换是不可能的。

Reflection(albiet unwieldy)或dynamic(基本上更容易使用 - 反射)允许调用任意方法或访问针对通用对象类型表达式的属性/字段 - 这偶尔会被称为“后期约束”。但是,调用操作的表达式的类型仍然是对象。

Interfaces可用于统一不同的类实现以进行适当的静态类型。然后可以将新创建​​的对象强制转换为适用的接口。就像其他表达式一样,类型是编译时构造(因此必须直接指定接口),但代码现在没有特定的类。

如果要创建一个系统,使这些“动态类”直接用于静态类型(C#)代码,并且接口可以保证或被约束到一个小集合,那么使用接口可能是最干净的方法:例如var myAction = (IMyAction)obj。否则,回到动态访问 - 直接或在幕后。

答案 1 :(得分:3)

将您的变量定义为dynamic并且它应该有效,我的意思是你仍然无法施放它但你可以访问你的方法:

dynamic obj = Activator.CreateInstance (type, new Object[]{ "argument" });

例如:

enter image description here

答案 2 :(得分:3)

根据您的评论,您尝试将其添加到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);

答案 3 :(得分:1)

如果您静态地知道基类的类型,则转换为该类型。例如:

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;

你也可以使用反射,但这相当麻烦,所以我不举一个例子。如果您具有在基本类型的不同子类型上定义的同名属性,但在基本类型上没有,则反射将非常有用。如果有许多子类型,则类型检查会变得很麻烦,因此反射可能是更好的方法。