我试图让所有特性从一种类型,但是使用TypeDescriptor.GetProperties(用这种类型)将仅提供我的特性,具有既定者和吸气。我只写的属性。有没有方法检索PropertyDescriptorCollection包括那些?

/Asger

有帮助吗?

解决方案

只写的性质是一种罕见的野兽,而且不存在的系统。ComponentModel(/PropertyDescriptor空间。 PropertyDescriptors是设计为可可读性。也许我可以破解 HyperDescriptor 为填写的-只有属性,但这将是一个黑客-它可能不得不放弃的例外情况 get, ,这可能影响调用代码相当多的。

作为一个撤销;我一般建议 反对 只写的属性;该文书的例子,人们一路小跑出来的是密码(public string Password {private get;set;})-我宁愿有一个 void SetPassword(string newPassword) 方法...

它是什么,你实际上想要做什么?有的选择范围,在这里,所有非常可以实现:

  • 使用反射单(慢;也许不是一个选项)
  • 使用 Delegate.CreateDelegate (很容易)
  • 使用 Expression.Compile (a 困难,但是不多)
  • 使用 Reflection.Emit (相当困难的)
  • 垫片只写成性 PropertyDescriptor (相当困难的)

如果你让我知道你其实想要做的(而不是你们目前正试图做到这一点),我可能能够帮助更多。

作为一个例子使用 Delegate.CreateDelegate (注意你想要藏匿处委托地方,并重新使用它很多次):

编辑,以显示如何做到这一点,如果你不知道具体类型的运行时

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(.净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();
    }
}

其他提示

使用 System.Type.GetProperties() 代替,返回所有属性。请注意,此返回PropertyInfo[]代替PropertyDescriptorCollection的。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top