代码之家  ›  专栏  ›  技术社区  ›  asgerhallas

typescriptor.getproperties(thistype)返回只写的属性

  •  1
  • asgerhallas  · 技术社区  · 15 年前

    我试图从一个类型中获取所有属性,但使用typescriptor.get properties(thistype)将只提供同时具有setter和getter的属性。我只有写属性。是否有方法检索包含这些内容的PropertyDescriptor集合?

    阿舍尔

    2 回复  |  直到 15 年前
        1
  •  9
  •   Marc Gravell    15 年前

    只写属性是一种罕见的野兽,在System.ComponentModel/PropertyDescriptor空间中不存在。 PropertyDescriptor S设计为可读。我可能会黑客 HyperDescriptor 填充只写属性,但这将是一个黑客攻击,并且可能必须抛出 get 这可能会对调用代码产生很大的影响。

    作为旁白;我通常建议 反对 只写属性;人们提出的文本手册示例是密码( public string Password {private get;set;} )-我宁愿吃一个 void SetPassword(string newPassword) 方法…

    你到底想做什么?这里有多种选择,都是可以实现的:

    • 单独使用反射(慢;可能不是一个选项)
    • 使用 Delegate.CreateDelegate (很容易)
    • 使用 Expression.Compile (A) 小的 更难,但不多)
    • 使用 Reflection.Emit (相当难)
    • 填充程序只将属性写入 属性描述器 (相当难)

    如果你让我知道你真正想做什么(而不是你目前试图做的方式),我可能会提供更多帮助。

    例如,使用 委托.创建委托 (请注意,您希望将代理存储在某个地方,并多次重复使用它):

    编辑以显示在运行时不知道特定类型时如何操作

    using System;
    using System.Reflection;
    
    class Foo
    {
        public string Bar { private get; set; }
        public override string ToString()
        {
            return Bar; // to prove working
        }
    }
    static class Program
    {
        static void Main()
        {
            ISetter setter = Setter.Create(typeof(Foo), "Bar");
            Foo foo = new Foo();
            setter.SetValue(foo, "abc");
            string s = foo.ToString(); // prove working
        }
    }
    public interface ISetter {
        void SetValue(object target, object value);
    }
    public static class Setter
    {
        public static ISetter Create(Type type, string propertyName)
        {
            if (type == null) throw new ArgumentNullException("type");
            if (propertyName == null) throw new ArgumentNullException("propertyName");
            return Create(type.GetProperty(propertyName));
        }
        public static ISetter Create(PropertyInfo property)
        {
            if(property == null) throw new ArgumentNullException("property");
            if (!property.CanWrite) throw new InvalidOperationException("Property cannot be written");
            Type type = typeof(TypedSetter<,>).MakeGenericType(
                    property.ReflectedType, property.PropertyType);
            return (ISetter) Activator.CreateInstance(
                type, property.GetSetMethod());
        }
    }
    
    public class TypedSetter<TTarget, TValue> : ISetter {
        private readonly Action<TTarget, TValue> setter;
        public TypedSetter(MethodInfo method) {
            setter = (Action<TTarget, TValue>)Delegate.CreateDelegate(
                typeof(Action<TTarget, TValue>), method);
        }
        void ISetter.SetValue(object target, object value) {
            setter((TTarget)target, (TValue)value);
        }
        public void SetValue(TTarget target, TValue value) {
            setter(target, value);
        }
    }
    

    或者使用 Expression API(.NET 3.5):

    using System;
    using System.Linq.Expressions;
    using System.Reflection;
    
    class Foo
    {
        public string Bar { private get; set; }
        public override string ToString()
        {
            return Bar; // to prove working
        }
    }
    static class Program
    {
        static void Main()
        {
            Action<object,object> setter = Setter.Create(typeof(Foo), "Bar");
            Foo foo = new Foo();
            setter(foo, "abc");
            string s = foo.ToString();
        }
    }
    
    public static class Setter
    {
        public static Action<object,object> Create(Type type, string propertyName)
        {
            if (type == null) throw new ArgumentNullException("type");
            if (propertyName == null) throw new ArgumentNullException("propertyName");
            return Create(type.GetProperty(propertyName));
        }
        public static Action<object,object> Create(PropertyInfo property)
        {
            if(property == null) throw new ArgumentNullException("property");
            if (!property.CanWrite) throw new InvalidOperationException("Property cannot be written");
    
            var objParam = Expression.Parameter(typeof(object), "obj");
            var valueParam = Expression.Parameter(typeof(object), "value");
            var body = Expression.Call(
                Expression.Convert(objParam, property.ReflectedType),
                property.GetSetMethod(),
                Expression.Convert(valueParam, property.PropertyType));
            return Expression.Lambda<Action<object, object>>(
                body, objParam, valueParam).Compile();
        }
    }
    
        2
  •  2
  •   Konrad Rudolph    15 年前

    使用 System.Type.GetProperties() 相反,它返回所有属性。注意,这会返回 PropertyInfo[] 而不是 PropertyDescriptorCollection .

    推荐文章