可以获取可为null和不可为null的变量的T方法

本文关键字:null 变量 方法 获取 | 更新日期: 2023-09-27 18:20:11

我想创建一个可以做以下事情的方法:

string? s = xelement.GetValue < string > ( "elementname" );
Guid? g = xelement.GetValue < Guid > ( "elementname" );
int? i = xelement.GetValue < int > ( "elementname" );
DateTime? d = xelement.GetValue < DateTime > ( "elementname" );

有可能吗?

可以获取可为null和不可为null的变量的T方法

恐怕您将不得不创建两个单独的方法。为了返回Nullable<T>,您需要struct约束,它可以防止使用引用类型。

尝试此扩展方法将适用于string、int和DateTime,因为IConvertable接口支持所有这些类型。因此,您可以将字符串转换为布尔、字节、字符、十进制等(Guid除外):

public static T GetValue<T>(this XElement element, string name)
{
    string value = (string)element.Element(name);
    return (T)Convert.ChangeType(value, typeof(T));
}

顺便说一句,C#中没有Nullable<string>,因为nullable只能接受值类型。所以你应该使用简单的字符串。


用法:

<rooot>
  <string>hello</string>
  <int>42</int>
  <guid>0FFF30ED-0C4B-41ED-9CDA-D9E084FAD6F2</guid>
  <date>06/27/2013</date>
</rooot>

分析:

XDocument xdoc = XDocument.Load(path_to_xml);
XElement root = xdoc.Root;
string s = root.GetValue<string>("string");
int? i = root.GetValue<int>("int");
DateTime? d = root.GetValue<DateTime>("date");

如果你想让guid也得到支持,那么你可以手动解析它们:

public static T GetValue<T>(this XElement element, string name)
{
    string value = (string)element.Element(name);    
    Type targetType =  typeof(T);
    if (targetType == typeof(Guid))
        return (T)(object)Guid.Parse(value);
    var typeConverter = TypeDescriptor.GetConverter(targetType);
    if (typeConverter == null || !typeConverter.CanConvertFrom(typeof(string)))
        return default(T); // or throw exception
    return (T)typeConverter.ConvertFrom(value);
}

UPDATE好的,如果你想从方法返回可为null的值,那么(记住,字符串不是值类型,所以你不能用string参数化方法):

public static Nullable<T> GetValue<T>(this XElement element, string name)
    where T : struct
{
    string value = (string)element.Element(name);
    if (value == null)
        return null;
    Type targetType =  typeof(T);
    if (targetType == typeof(Guid))
        return (T)(object)Guid.Parse(value);
    var typeConverter = TypeDescriptor.GetConverter(targetType);
    if (typeConverter == null || !typeConverter.CanConvertFrom(typeof(string)))
        return null; // or throw exception
    return (T)typeConverter.ConvertFrom(value);
}

您可以使用"Null对象"模式。此处

我在LinqPad(我的快速C#沙箱)中测试了它,它可以工作:

    void Main()
{
    string s = GetValue<string>("elementname");
    Guid? g = GetValue<Guid?>("elementname");
    Guid h = GetValue<Guid>("elementname");
    int? i = GetValue<int?>("elementname");
    int j = GetValue<int>("elementname");
    DateTime? d = GetValue<DateTime?>("elementname");
    DateTime e = GetValue<DateTime>("elementname");
    Console.WriteLine(s);
    Console.WriteLine(g);
    Console.WriteLine(h);
    Console.WriteLine(i);
    Console.WriteLine(j);
    Console.WriteLine(d);
    Console.WriteLine(e);
}
T GetValue<T>(string elementName)
{
    return default(T);
}

输出:

null 
null 
00000000-0000-0000-0000-000000000000
null 
0
null 
1-1-0001 00:00:00