【问题标题】:how to recursively call a generic method analyzing properties如何递归调用分析属性的泛型方法
【发布时间】:2015-04-19 05:36:59
【问题描述】:

我正在创建一个方法来分析我创建的类的实例,检查该类上的每个属性是否有 string 类型,然后检查这些 string 属性是否为 null 或空.

代码:

public class RootClass
{
    public string RootString1 { get; set; }
    public string RootString2 { get; set; }
    public int RootInt1 { get; set; }

    public Level1ChildClass1 RootLevel1ChildClass11 { get; set; }
    public Level1ChildClass1 RootLevel1ChildClass12 { get; set; }
    public Level1ChildClass2 RootLevel1ChildClass21 { get; set; }
}

public class Level1ChildClass1
{
    public string Level1String1 { get; set; }
    public string Level1String2 { get; set; }
    public int Level1Int1 { get; set; }
}

public class Level1ChildClass2
{
    public string Level1String1 { get; set; }
    public string Level1String2 { get; set; }
    public int Level1Int1 { get; set; }

    public Level2ChildClass1 Level1Level2ChildClass11 { get; set; }
    public Level2ChildClass1 Level1Level2ChildClass12 { get; set; }
    public Level2ChildClass2 Level1Level2ChildClass22 { get; set; }
}

public class Level2ChildClass1
{
    public string Level2String1 { get; set; }
    public string Level2String2 { get; set; }
    public int Level2Int1 { get; set; }
}

public class Level2ChildClass2
{
    public string Level2String1 { get; set; }
    public string Level2String2 { get; set; }
    public int Level2Int1 { get; set; }
}

类上的属性并不是所有的都是字符串,有些是其他类的实例,它们有自己的属性,也需要用同样的方法来分析。基本上,如果任何属性是在 RootClass 或类的任何子级别上具有值的字符串(例如,如果 RootLevel1ChildClass11 具有带值的字符串属性),该方法将返回 true

这是我目前所拥有的:

public static bool ObjectHasStringData<T>(this T obj)
{
    var properties = typeof(T).GetProperties(BindingFlags.NonPublic | BindingFlags.Instance);
    foreach (var property in properties)
    {
        Type propertyType = property.PropertyType;
        if (propertyType == typeof(string))
        {
            try
            {
                if (!String.IsNullOrEmpty(property.GetValue(obj, null) as string))
                    return true;
            }
            catch (NullReferenceException) { } // we want to ignore NullReferenceExceptions
        }
        else if (!propertyType.IsValueType)
        {
            try
            {
                if (ObjectHasStringData(property.GetValue(obj, null)))
                    return true;
            }
            catch (NullReferenceException) { } // we want to ignore NullReferenceExceptions
        }
    }
    return false;
}

这在第一层上效果很好(所以RootClass 中的任何string),但是一旦我开始在if (ObjectHasStringData(property.GetValue(obj, null))) 行上递归地使用它,property.GetValue() 的返回值是object,所以递归调用方法时,Tobject

我可以得到当前对象的Type,但是如何将property.GetValue()返回的object转换为属性的实际类型呢?

【问题讨论】:

    标签: c# generics reflection


    【解决方案1】:

    我建议不要把它作为一个通用方法,让它接受任何对象,并使用GetType 来获取类型(除非它是空的)。泛型在这里似乎并没有真正增加任何价值。

    所以,去掉类型参数,使用obj.GetType(),如果对象为null就不要递归!

    另外,(propertyType)obj) 也不起作用,如果可以,它也没有用。强制转换仅用于类型安全并确定(在编译时)如何与对象交互。对 System.Reflection 没有任何区别。

    public static bool ObjectHasStringData( this object obj )
    {
        if( obj == null )
            return false;
        var properties = obj.GetType().GetProperties(BindingFlags.NonPublic | BindingFlags.Instance);
        foreach (var property in properties)
         ...
    }
    

    【讨论】:

    • 我想我认为使用object.GetType() 会返回object,而不是实际对象的类型......不过它似乎正在工作,所以我要测试一下然后标记为答案
    • 对象的类型不会随着投射而改变——它只会改变你与它交互的方式。因此GetType 将始终返回基础类型,无论您如何引用它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-26
    • 1970-01-01
    • 1970-01-01
    • 2020-05-16
    • 1970-01-01
    • 2011-05-18
    相关资源
    最近更新 更多