使用反射给实例的属性赋值

我们经常有这样的需求,就是我们需要使用属性名来给属性赋值,而不能直接使用类似obj.prop = value这种方式。

比如我们有有一个Dictionary,key是属性名,value是属性值。我们需要把它们变成一个对象,就可以使用这种方式。


这里我们的代码可以这样写:

        public static void SetProperty(object obj, string name, object value, BindingFlags bindingFlags = BindingFlags.Public)
        {
            var t = obj.GetType();
            var p = t.GetProperty(name, bindingFlags);

            if (p == null)
            {
                throw new InvalidOperationException($"未找到 {name} 属性");
            }

            if (!p.PropertyType.IsGenericType)
            {
                p.SetValue(obj, Convert.ChangeType(value, p.PropertyType));
            }
            else
            {
                var genericTypeDefinition = p.PropertyType.GetGenericTypeDefinition();
                if (genericTypeDefinition == typeof(Nullable<>))
                {
                    p.SetValue(obj,
                        Convert.ChangeType(value,
                            Nullable.GetUnderlyingType(p.PropertyType) ??
                            throw new InvalidOperationException("获取类型失败")));
                }
                else
                {
                    throw new InvalidOperationException("只能对基础类型进行赋值");
                }
            }
        }

这里注意几个问题,就是首先我们获取Property的时候是可以处理BindingFlags的,如果我们还需要处理私有属性或者静态属性,这里可以修改BindingFlags

这种p.SetValue的方法不能给泛型类型赋值,所以这里就只能判断一下p.PropertyType.IsGenericType,看是否为泛型类型。


但是泛型类型中有一个特例,就是Nullable,这玩意是个啥呢,就是int?这种可空类型。


可空类型是可以给他进行赋值的,所以我们这里判断一下是否为可空类型。genericTypeDefinition == typeof(Nullable<>),如果是可空类型的话就使用Nullable.GetUnderlyingType获取其真实类型转换后赋值。


最后我们还可以把它做成object的扩展,直接在任意对象上都可以使用,这就是我的jx.toolbox中的做法了。

posted @ 2022-09-16 17:58  jvx  阅读(1315)  评论(0编辑  收藏  举报