从类型名称获取可空类型

5

我有一个这样的场景,我得到了一个看起来像下面这样的字符串

"System.DateTime?"

或者

"int?"

我希望能够做到的是,获取该字符串的 System.Type,它应该如下所示: {Name = "Nullable1" FullName = "System.Nullable1[[System.DateTime, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]"}
现在我知道如何从字符串中获取类型,当处理非可空类型时,我可以使用 Type.GetType("System.DateTime"),或者当我知道它将是 DateTime 可空时,可以使用 typeof(DateTime?)。但在这种情况下,我不知道可能出现的可空类型是什么,只会以字符串形式接收它。

我猜应该是 Nullable<T> - gunr2171
那个字符串是由什么生成的,为什么它没有为类型生成一个合适的名称? - Servy
参见 / 可能是 https://dev59.com/4HrZa4cB1Zd3GeqP12by 的重复问题。 - gunr2171
@gunr2171 他们有一个字符串,而不是一个“Type”,所以那篇帖子并没有真正帮助到他们。他们也不需要底层类型,他们想要的是“Nullable”“Type”值。 - Servy
你是否需要支持.NET中任何可能命名合法类型的字符串,还是只需要支持有限的子集?我问这个问题是因为...你需要支持这个字符串吗?"Namespace1.Namespace2.Generic<int, string>.Nested.Inner<DateTime>.NestedInner<int?>" - Lasse V. Karlsen
3个回答

5

我不清楚上下文的完整性 - 比如说,这个字符串是否总是代表可空值类型?

鉴于你可以从字符串中提取值类型名称并创建对该类型的引用:

var valueType = Type.GetType("System.DateTime");
var nullableType = typeof(Nullable<>).MakeGenericType(valueType);

这会解决问题的一部分。更难的部分就是从字符串中确定底层类型,这取决于您收到什么样的输入。从 System.DateTime 中获取一个类型很容易,但从 int 中获取则比较困难。 这个答案 可能对此有所帮助。


至于输入 - 是否有任何选项,您可以向用户提供可用选择列表,以便您接收到的输入始终是有效的类型名称?那样就不需要这些了。然后,您只需执行 Type.GetType(stringWithTypeName)


5
除了Scott的回答,您还可以使用正确的名称使用Type.GetType:
System.Nullable`1[System.DateTime]

所以这个函数会为你返回正确的类型。
public Type GetType(string typeString)
{
    if (typeString.EndsWith("?"))
    {
        typeString = $"System.Nullable`1[{typeString.TrimEnd('?')}]";
    }
    return Type.GetType(typeString);
}

或者只需使用 typeString.TrimEnd('?')。我最初打算包括这部分,但输入有点让我困惑。如果它是一个可靠的类型名称,则可以正常工作,但如果它是一个别名,如 int 或缺少命名空间,则无法正常工作。我相信有解决方法,但意图似乎不明确。 - Scott Hannen
是的...“TrimEnd”听起来更好。我忘了。谢谢。关于别名,就像你所说,它不起作用,Jon Skeet在他提供的链接中给出了一个很好的“复制/粘贴”字典,OP可以使用。 - Ofir Winegarten

1

解决这个问题的一种方法是为类型“Type”创建一个扩展方法,并使该方法的实现检查它是否为可空类型并返回正确的类型。以下是示例:

namespace ExtensionMethod  
    {
        public static class MyExtensions
        {
            public static Type GetNullabeType(this Type t, string typeName)
            {
                string typeString = typeName;
                var typeNonNullabe = Type.GetType(typeString.Replace("?", ""));
                if (typeString.Contains("?") && typeNonNullabe != null)
                {
                    return typeof(Nullable<>).MakeGenericType(typeNonNullabe);
                }
                return t;
            }
        }
    }

之后,只需按照以下方式使用此扩展方法:

Type t = null;
var type = t.GetNullabeType("System.DateTime?");

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接