2009-04-21 3 views
1

형식에서 모든 속성을 가져 오려고하는데 TypeDescriptor.GetProperties (thisType)를 사용하면 setter와 게터. 쓰기 전용 속성이 있습니다. 그 (것)들을 포함하여 PropertyDescriptorCollection를 만회하는 방법 있는가? 모든 속성을 반환하는 대신TypeDescriptor.GetProperties (thisType)는 쓰기 전용 속성을 반환합니다.

/Asger

+0

귀하의 의견; 유형을 모르는 경우 "트릭"으로 업데이트를 게시합니다 ... –

+0

사실, 방금 귀하의 의견을 다시 읽었습니다. 인터페이스의 쓰기 전용 속성입니까? 그렇다면 원래 코드를 사용하고 (수정 사항 참조) 인터페이스를 반사 된 유형으로 사용할 수 있습니다. –

+0

예 속성이 인터페이스에 있습니다. 원래 예제를 사용하여 (편집 전에, 그것이 의미하는 것이 있다면?) 시도했지만 대리자를 바인딩 할 수 없다는 예외가 발생했습니다. - 또는 실제 예외 메시지를 얻기 위해 다시 시도해야합니다. . – asgerhallas

답변

9

쓰기 전용 속성은 드물 긴하지만 System.ComponentModel/PropertyDescriptor 공간에는 존재하지 않습니다. PropertyDescriptor은 읽을 수 있도록 설계되었습니다. 쓰기 전용 속성을 shim하려면 HyperDescriptor을 해킹 할 수는 있지만 해킹이 될 수 있으며 get에 대한 예외를 throw해야 할 수도 있습니다. 이는 코드 호출에 상당한 영향을 줄 수 있습니다.

제쳐두고; 나는 일반적으로 조언을 에 대해 쓰기 전용 속성; 사람들이 골라내는 교과서 예제는 암호 (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 (.NET 3.5)를 사용하여 :

+0

안녕하세요 마크, 신속하게 회신 해 주셔서 감사합니다! setters는 webforms 응용 프로그램의 일부보기 요소를 구성하기위한 프록시로 작동합니다. 발표자는보기 인터페이스를 통해보기에 필요한 구성을 설정합니다. 인터페이스에서의 반사 및보기 구현을 사용하여 결국 SetValue를 사용하여보기에서 구성을 설정합니다. 우리 시스템이 커지고 서로 (내부에 중첩 된) 많은 견해가있어 반사 부분이 정말로 느립니다. – asgerhallas

+0

당신의 대리자 솔루션이 나에게 맞는 접근법 인 것 같아 - 나는 일반 클래스에서 숨겨진 SetValue에 대한 논리를 가지고있다. 나는 그것을 즉시 시험해 보러 갈 것이다. 추천하는 다른 가능성에 대해 더 많은 문서/"시작하기 writeups"가 있습니까? – asgerhallas

+0

저는 좀 더 자세히 살펴 보았습니다. 위임 솔루션의 한 가지 문제점은 컴파일시 Foo가 구현 한 인터페이스 만보기 구현의 유형 (Foo)을 알지 못한다는 것입니다. 런타임에는 유형이 있습니다. 그러면 대표를 만들기 위해 리플렉션을 사용해야합니다. 그러면 퍼포먼스가 망가질 지 모르겠습니다 ... – asgerhallas

2

사용 System.Type.GetProperties(). 이 값은 PropertyDescriptorCollection 대신 PropertyInfo[]을 반환합니다.

+1

FYI : 매개 변수없는 버전 만 모든 공개 속성을 반환합니다.원하는 경우 BindingFlags를 사용하여 모든 속성을 가져 오는 오버로드가 있습니다. –

+0

도움에 감사드립니다. 하지만 OG 성능 문제 때문에 Marc Gravell HyperTypeDescriptor를 사용하고있어 PropertyDescriptor가 아니라 PropertyInfo가 필요합니다. 따라서 Type.GetProperties를 사용하는 것은 불행히도 해결책이 아닙니다. – asgerhallas

+0

내 이름이 호출되는 것을 들었습니까? 답장을 추가하겠습니다 ... –

관련 문제