如何将类型变量用作类型?

时间:2017-08-15 17:16:42

标签: c# types casting

修改
这两个问题都不回答我的问题。也许是解决这个问题的更好方法:
如何将类型变量用作类型?
如何使用字符串强制转换为类型来声明Type变量?

示例,请参阅:
 Document document = ((document)modelObject);

此处使用了Document类型,但是我说我不知道​​我的modelObject是一个文档,我将如何获取它?

假设的想象解决方案,其中t是文档

Type t = Type.GetType(type.Name);  
t tVar = ((t)modelObject);

在我上面的示例中,它不起作用,因为“'t'是一个变量,但用作类型”

ORIGINAL
我有一个控制结构,我想用它来处理动态出现的不同类型。这些类型使用 type.Name 收集,然后根据此类型输入控制结构。我想要做的是保持文件夹的控制结构,以便我可以继续处理文件夹功能(允许文件夹的扩展等),但是相互推广,以便它们都可以在一个单一的结构,而不是一遍又一遍地复制结构,但稍微改变了要处理的类型。

所以,我的结构(粗略地)看起来像这样:

Type type = modelObject.GetType();
if (type.Name == "Folder")
{
    Folder folder = ((Folder)modelObject);
    TreeNode NewNode = new TreeNode(folder.Object_string);

    NewNode.Tag = folder;

    CurrentRootNode.Nodes.Add(NewNode);
    if (fRecursive)
    {
        ModelObject[] objects = { modelObject };
        String[] attributes = { "contents" };

        WorkspaceObject[] NewNodeContents = ((Folder)modelObject).Contents;

        AddContentsToNode(NewNode, NewNodeContents, true);
    }
    else
    {
        TreeNode EmptyNode = new TreeNode("");
        NewNode.Nodes.Add(EmptyNode);
    }
}

if (type.Name == "STL")
{
    STL stl = ((STL)modelObject);
    TreeNode NewNode = new TreeNode(stl.Object_string);

    NewNode.Tag = stl;

    CurrentRootNode.Nodes.Add(NewNode);
}

if (type.Name == "Document")
{
    Document document = ((Document)modelObject);
    TreeNode NewNode = new TreeNode(document.Object_string);

    NewNode.Tag = document;

    CurrentRootNode.Nodes.Add(NewNode);
}

注意STL和Document类型的处理方式完全相同,只是稍微改变了它们被处理的类型。 理想情况下,它看起来像这样:

if (type.Name == "Folder")
{ ... }
else
{
    (Type)type.Name tn = (((Type)type.Name)modelObject);
    TreeNode NewNode = new TreeNode(tn.Object_string);

    NewNode.Tag = tn;

    CurrentRootNode.Nodes.Add(NewNode);
}

但是,如上所示,type.Name是一个字符串 (类型)类型。悬停时的名称文字 - Cannot convert type 'string' to 'System.Type'

所以问题是:

是否有“通用”方式将字符串转换为Type,或根据字符串分配Type?

我似乎无法找到任何通用的方法来全面处理类型声明(类似理想的示例将是理想的!)。

3 个答案:

答案 0 :(得分:0)

您可以使用Type.GetType重叠,但是您应该使用FullName而不是名称,因为名称可能会导致含糊不清。

string type = typeof(Program).FullName;
var typeObj = Type.GetType(type);

当然这只会给你类的类型,而不是实际的实例。

答案 1 :(得分:0)

虽然将字符串转换为类型并不是那么困难,但我必须指出你是以错误的方式解决这个问题。您永远不必将类型存储在字符串中,就像您永远不会将数字存储在字符串中或日期存储在字符串中一样。

如果要检查一系列类型,并为每种类型执行不同的操作,请遵循以下模式:

public void HandleModelObject(object modelObject)
{
    var folder = modelObject as Folder;
    if (folder != null)
    {
        TreeNode NewNode = new TreeNode(folder.Object_string);
        return;
    }
    var document = modelObject as Document;
    if (document != null)
    {
        TreeNode NewNode = new TreeNode(document.Object_string);
        return;
    }
    var someOtherType = modelObject as SomeOtherType;
    if (someOtherType != null)
    {
        TreeNode NewNode = new TreeNode(someOtherType.Object_string);
        return;
    }
}

此外,我建议您为可以出现在树节点中的所有对象添加公共接口,例如: IExplorable或其他什么。那么你甚至不必演员:

interface IExplorable
{
    string Object_string { get; set; }
}

class Folder : IExplorable
{
    public string Object_string { get; set; }
}

class Document : IExplorable
{
    public string Object_string { get; set; }
}

public void HandleModelObject(IExplorable modelObject)
{

    TreeNode NewNode = new TreeNode(modelObject.Object_string);  //No if or cast required at all
}

如果您不想要一个界面,并且希望能够处理任何对象,那么您可以使用的唯一属性是GetType()ToString(),它们对所有对象都是通用的。解决方案很短:

public void HandleModelObject(object modelObject)
{
    TreeNode NewNode = new TreeNode(modelObject.ToString());
}

如果您只需要处理对象的子集,但它们没有共同的接口,但它们确实具有公共属性(例如string Object_string),那么您可以使用一些反射。这是最后的手段。

public void HandleModelObject(object modelObject)
{
    var value = modelObject.GetType().GetProperty("Object_string", BindingFlags.Instance).GetValue(modelObject) as string;
    TreeNode NewNode = new TreeNode(value);
}

当然,如果您错误地提供了错误类型的对象并且它没有Object_string属性,您将需要进行空检查。

答案 2 :(得分:0)

我无法将字符串转换为类型,然后将它们用作类型。从我的研究来看,这是不可能的。重复的标记也没有产生任何结果。相反,我现在可以实现的唯一解决方法是预先将TC类型添加为直接没有处理类型的节点。