typedescriptor.getProperties (thistype)는 쓰기 전용 인 속성을 반환합니다.
-
12-09-2019 - |
문제
나는 유형에서 모든 속성을 얻으려고 노력하고 있지만 typedescriptor.getProperties (thistype)를 사용하면 setter와 getter가있는 속성 만 제공합니다. 쓰기 전용 속성이 있습니다. 그것들을 포함하여 PropertyDescriptorCollection을 검색하는 방법이 있습니까?
/ASGER
해결책
쓰기 전용 속성은 희귀 한 짐승이며 System.componentModel / PropertyDescriptor Space에는 존재하지 않습니다. PropertyDescriptor
S는 읽을 수 있도록 설계되었습니다. 아마 해킹 할 수 있습니다 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
.