代码之家  ›  专栏  ›  技术社区  ›  Liran Friedman

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

  •  3
  • Liran Friedman  · 技术社区  · 7 年前

    我有以下扩展方法,用于填充来自同一类的源对象的类成员缺少的值。该方法缺少的部分是,该类的一个成员也是另一个类的一个类对象,而另一个类也有自己的成员,因此我在这里需要一个递归,但我没有找到任何方法来获取该类成员的内部成员并能够将其传递回 FillValues 方法

    例如,我有一个名为 User 还有一个叫做 UserLogin 这样地:

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

    当我打电话时 填充值 关于班级成员 使用者 如果从中填写缺少的字段 FirstName LastName 但不是来自 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 回复  |  直到 7 年前
        1
  •  2
  •   Titian Cernicova-Dragomir    7 年前

    您需要递归调用 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);
            }
        }
    }