我试图从一个类型中获取所有属性,但使用 TypeDescriptor.GetProperties(thisType) 只会为我提供同时具有 setter 和 getter 的属性。我有只写属性。有没有办法检索包含这些的 PropertyDescriptorCollection?
/阿斯格
最佳答案
只写属性是一种罕见的野兽,在 System.ComponentModel/PropertyDescriptor 空间中不存在。 PropertyDescriptor
被设计为可读的。我可能可以破解 HyperDescriptor
来填充只写属性,但这将是一个破解 - 并且它可能必须为 get
抛出异常,这可能会相当影响调用代码有一点。
顺便说一句;我通常建议反对只写属性;人们在教科书中举出的例子是密码 (public string Password {private get;set;}
) - 我更愿意有一个 void SetPassword(string newPassword)
方法...
你真正想做的是什么?这里有一系列选项,都非常容易实现:
- 单独使用反射(慢;可能不是一种选择)
- 使用
Delegate.CreateDelegate
(非常简单) - 使用
Expression.Compile
(稍微更难,但不多) - 使用
Reflection.Emit
(相当困难) - 将只写属性填充到
PropertyDescriptor
中(很难)
如果您让我知道您实际想做什么(而不是您目前正在尝试做的方式),我可能会提供更多帮助。
作为使用 Delegate.CreateDelegate
的示例(请注意,您可能希望将委托(delegate)存储在某个地方并多次重复使用它):
编辑以展示如果您在运行时不知 Prop 体类型时如何操作
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();
}
}
关于c# - TypeDescriptor.GetProperties(thisType) 返回只写的属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/772107/