typedescriptor.getProperties (Thistype) لإرجاع الخصائص، والتي هي الكتابة فقط

StackOverflow https://stackoverflow.com/questions/772107

سؤال

أحاول الحصول على جميع الخصائص من نوع، ولكن باستخدام TypedEScriptor.getProperties (Thistype) ستزودني فقط بالخصائص، والتي تحتوي على Sedter و A Getter. لدي خصائص الكتابة فقط. هل هناك طريقة لاسترداد خصائص PropertyDescriptorCollection بما في ذلك تلك؟

/ asgher.

هل كانت مفيدة؟

المحلول

خصائص الكتابة فقط هي وحش نادر، ولا توجد في مساحة System.componentModel / PropertyDescriptor. PropertyDescriptorS مصممة لتكون مقروءة. ربما يمكن أن اختراق HyperDescriptor إلى خصائص الكتابة فقط، ولكنها ستكون اختراقا - وسوف تضطر إلى إلقاء استثناءات 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[] بدل من PropertyDescriptorCollection.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top