C# - 如何获取类成员的属性,这也是一个类?

时间:2018-02-12 15:31:57

标签: c# reflection

我有以下扩展方法,它从同一个类的源对象中填充类成员的缺失值。这个方法缺少的部分是当一个类的成员也是另一个类的类对象时,它也有自己的成员,所以我需要一个递归,但是我没有找到任何方法来获取内部成员类成员并能够将其传递回FillValues方法...

例如,我有一个名为User的类和一个名为UserLogin的类,如下所示:

public class User
{
    public string FirstName;
    public string LastName;
    public UserLogin Login;
}

public class UserLogin
{
    public string Email;

    public string Password;
}

如果我在FillValuesUser填写了缺少的字段,而不是来自FirstName,则我会在LastName班级成员上致电Login班级成员。

如何递归传递成员Login,以便嵌套成员也可以填充值?

public static void FillValues<T>(this T target, T source)
{
    FillMissingProperties(target, source);
    FillMissingFields(target, source);
}

private static void FillMissingProperties<T>(T target, T source)
{
    var properties = typeof(T).GetProperties().Where(prop => prop.CanRead && prop.CanWrite);
    foreach (var prop in properties)
    {
        var targetValue = prop.GetValue(target, null);
        var defaultValue = prop.PropertyType.GetTypeInfo().IsValueType ? Activator.CreateInstance(prop.PropertyType) : null;

        if (targetValue == null || targetValue.Equals(defaultValue))
        {
            var sourceValue = prop.GetValue(source, null);
            prop.SetValue(target, sourceValue, null);
        }
    }
}

private static void FillMissingFields<T>(T target, T source)
{
    var fields = typeof(T).GetFields();
    foreach (var field in fields)
    {
        var targetValue = field.GetValue(target);
        var sourceValue = field.GetValue(source);
        var defaultValue = field.FieldType.GetTypeInfo().IsValueType ? Activator.CreateInstance(field.FieldType) : null;

        if (targetValue == null || targetValue.Equals(defaultValue))
            field.SetValue(target, sourceValue);
    }
}

1 个答案:

答案 0 :(得分:2)

您需要递归调用FillValues来获取类类型的类字段/属性。为此,您需要具有此方法的非泛型版本:

public static void FillValues<T>(this T target, T source)
{
    FillValues(typeof(T), target, source);
}

private static void FillValues(Type type, object target, object source)
{
    FillMissingProperties(type, target, source);
    FillMissingFields(type, target, source);
}
private static void FillMissingProperties(Type type, object target, object source)
{
    var properties = type.GetProperties().Where(prop => prop.CanRead && prop.CanWrite);
    foreach (var prop in properties)
    {
        var targetValue = prop.GetValue(target, null);
        var defaultValue = prop.PropertyType.GetTypeInfo().IsValueType ? Activator.CreateInstance(prop.PropertyType) : null;

        if (targetValue == null || targetValue.Equals(defaultValue))
        {
            var sourceValue = prop.GetValue(source, null);
            prop.SetValue(target, sourceValue, null);
        }
        else if (targetValue != null && prop.PropertyType != typeof(string) && prop.PropertyType.GetTypeInfo().IsClass)
        {
            var sourceValue = prop.GetValue(source, null);
            FillValues(prop.PropertyType, targetValue, sourceValue);
        }
    }
}

private static void FillMissingFields(Type type, object target, object source)
{
    var fields = type.GetFields();
    foreach (var field in fields)
    {
        var targetValue = field.GetValue(target);
        var sourceValue = field.GetValue(source);
        var defaultValue = field.FieldType.GetTypeInfo().IsValueType ? Activator.CreateInstance(field.FieldType) : null;

        if (targetValue == null || targetValue.Equals(defaultValue))
        {
            field.SetValue(target, sourceValue);
        }
        else if(targetValue != null && field.FieldType  != typeof(string) && field.FieldType.GetTypeInfo().IsClass)
        {
            FillValues(field.FieldType, targetValue, sourceValue);
        }
    }
}