문제

나는 유형에서 모든 속성을 얻으려고 노력하고 있지만 typedescriptor.getProperties (thistype)를 사용하면 setter와 getter가있는 속성 만 제공합니다. 쓰기 전용 속성이 있습니다. 그것들을 포함하여 PropertyDescriptorCollection을 검색하는 방법이 있습니까?

/ASGER

도움이 되었습니까?

해결책

쓰기 전용 속성은 희귀 한 짐승이며 System.componentModel / PropertyDescriptor Space에는 존재하지 않습니다. PropertyDescriptorS는 읽을 수 있도록 설계되었습니다. 아마 해킹 할 수 있습니다 HyperDescriptor 쓰기 전용 속성을 shim하기 위해서는 해킹 일 것입니다. 아마도 예외를 제외해야 할 것입니다. get, 코드 호출에 상당히 영향을 줄 수 있습니다.

여담으로; 나는 일반적으로 조언합니다 에 맞서 쓰기 전용 속성; 사람들이 트로트 아웃하는 교과서 예는 암호입니다 (public string Password {private get;set;}) - 나는 오히려 훨씬 가질 것입니다 void SetPassword(string newPassword) 방법...

실제로하고 싶은 것은 무엇입니까? 여기에는 다양한 옵션이 있습니다.

  • 반사 만 사용하십시오 (느린; 옵션이 아닐 수도 있습니다)
  • 사용 Delegate.CreateDelegate (아주 쉽게)
  • 사용 Expression.Compile (ㅏ 작은 더 어렵지만 많지는 않음)
  • 사용 Reflection.Emit (꽤 힘들다)
  • Shim 쓰기 전용 속성 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 (.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();
    }
}

다른 팁

사용 System.Type.GetProperties() 대신, 모든 속성을 반환합니다. 이것이 반환된다는 점에 주목하십시오 PropertyInfo[] 대신 a PropertyDescriptorCollection.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top