سؤال

وبالنظر إلى هذه الدرجة

class Foo
{
    // Want to find _bar with reflection
    [SomeAttribute]
    private string _bar;

    public string BigBar
    {
        get { return this._bar; }
    }
}

أريد أن العثور على البند الخاص _bar التي سيتم وضع علامة مع السمة.هل هذا ممكن ؟

أنا فعلت هذا مع خصائص حيث كنت قد بحثت عن سمة ، ولكن لا أحد أعضاء المجال.

ما هي ملزمة أعلام أعتقد أن الحصول على الخاص الحقول ؟

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

المحلول

استخدام BindingFlags.NonPublic و BindingFlags.Instance أعلام

FieldInfo[] fields = myType.GetFields(
                         BindingFlags.NonPublic | 
                         BindingFlags.Instance);

نصائح أخرى

يمكنك أن تفعل ذلك فقط مثل مع خاصية:

FieldInfo fi = typeof(Foo).GetField("_bar", BindingFlags.NonPublic | BindingFlags.Instance);
if (fi.GetCustomAttributes(typeof(SomeAttribute)) != null)
    ...

الحصول على الخاص متغير قيمة باستخدام التفكير:

var _barVariable = typeof(Foo).GetField("_bar", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(objectForFooClass);

تعيين القيمة الخاصة متغير باستخدام التفكير:

typeof(Foo).GetField("_bar", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(objectForFoocClass, "newValue");

حيث objectForFooClass غير null سبيل المثال نوع فئة فو.

الشيء الوحيد الذي كنت بحاجة إلى أن تكون على علم عند التفكير في الأعضاء خاصة هو أنه إذا كان التطبيق الخاص بك يعمل في ثقة متوسطة (على سبيل المثال ، عندما كنت تعمل على بيئة استضافة مشتركة) فلن تجد لهم-على BindingFlags.غير معلنة الخيار ببساطة لا يمكن تجاهلها.

typeof(MyType).GetField("fieldName", BindingFlags.NonPublic | BindingFlags.Instance)

جميلة الجملة مع طريقة التمديد

يمكنك الوصول إلى أي حقل خاص التعسفي نوع مع رمز مثل هذا:

Foo foo = new Foo();
string c = foo.GetFieldValue<string>("_bar");

لذلك تحتاج إلى تحديد طريقة التمديد التي سوف قيام بهذا العمل بالنسبة لك:

public static class ReflectionExtensions {
    public static T GetFieldValue<T>(this object obj, string name) {
        // Set the flags so that private and public fields from instances will be found
        var bindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
        var field = obj.GetType().GetField(name, bindingFlags);
        return (T)field?.GetValue(obj);
    }
}

يمكنني استخدام هذا الأسلوب شخصيا

if (typeof(Foo).GetFields(BindingFlags.NonPublic | BindingFlags.Instance).Any(c => c.GetCustomAttributes(typeof(SomeAttribute), false).Any()))
{ 
    // do stuff
}

نعم ، ولكن سوف تحتاج إلى تعيين ملزمة أعلام للبحث عن حقول خاصة (إذا كنت تبحث عن الأعضاء خارج الطبقة سبيل المثال).

ربط العلم سوف تحتاج إلى:النظام.انعكاس.BindingFlags.غير معلنة

هنا بعض طرق الإرشاد بسيطة على مجموعة حقول خاصة و خصائص (properties مع واضع):

استخدام على سبيل المثال:

    public class Foo
    {
        private int Bar = 5;
    }

    var targetObject = new Foo();
    var barValue = targetObject.GetMemberValue("Bar");//Result is 5
    targetObject.SetMemberValue("Bar", 10);//Sets Bar to 10

كود:

    /// <summary>
    /// Extensions methos for using reflection to get / set member values
    /// </summary>
    public static class ReflectionExtensions
    {
        /// <summary>
        /// Gets the public or private member using reflection.
        /// </summary>
        /// <param name="obj">The source target.</param>
        /// <param name="memberName">Name of the field or property.</param>
        /// <returns>the value of member</returns>
        public static object GetMemberValue(this object obj, string memberName)
        {
            var memInf = GetMemberInfo(obj, memberName);

            if (memInf == null)
                throw new System.Exception("memberName");

            if (memInf is System.Reflection.PropertyInfo)
                return memInf.As<System.Reflection.PropertyInfo>().GetValue(obj, null);

            if (memInf is System.Reflection.FieldInfo)
                return memInf.As<System.Reflection.FieldInfo>().GetValue(obj);

            throw new System.Exception();
        }

        /// <summary>
        /// Gets the public or private member using reflection.
        /// </summary>
        /// <param name="obj">The target object.</param>
        /// <param name="memberName">Name of the field or property.</param>
        /// <returns>Old Value</returns>
        public static object SetMemberValue(this object obj, string memberName, object newValue)
        {
            var memInf = GetMemberInfo(obj, memberName);


            if (memInf == null)
                throw new System.Exception("memberName");

            var oldValue = obj.GetMemberValue(memberName);

            if (memInf is System.Reflection.PropertyInfo)
                memInf.As<System.Reflection.PropertyInfo>().SetValue(obj, newValue, null);
            else if (memInf is System.Reflection.FieldInfo)
                memInf.As<System.Reflection.FieldInfo>().SetValue(obj, newValue);
            else
                throw new System.Exception();

            return oldValue;
        }

        /// <summary>
        /// Gets the member info
        /// </summary>
        /// <param name="obj">source object</param>
        /// <param name="memberName">name of member</param>
        /// <returns>instanse of MemberInfo corresponsing to member</returns>
        private static System.Reflection.MemberInfo GetMemberInfo(object obj, string memberName)
        {
            var prps = new System.Collections.Generic.List<System.Reflection.PropertyInfo>();

            prps.Add(obj.GetType().GetProperty(memberName,
                                               System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance |
                                               System.Reflection.BindingFlags.FlattenHierarchy));
            prps = System.Linq.Enumerable.ToList(System.Linq.Enumerable.Where( prps,i => !ReferenceEquals(i, null)));
            if (prps.Count != 0)
                return prps[0];

            var flds = new System.Collections.Generic.List<System.Reflection.FieldInfo>();

            flds.Add(obj.GetType().GetField(memberName,
                                            System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance |
                                            System.Reflection.BindingFlags.FlattenHierarchy));

            //to add more types of properties

            flds = System.Linq.Enumerable.ToList(System.Linq.Enumerable.Where(flds, i => !ReferenceEquals(i, null)));

            if (flds.Count != 0)
                return flds[0];

            return null;
        }

        [System.Diagnostics.DebuggerHidden]
        private static T As<T>(this object obj)
        {
            return (T)obj;
        }
    }

جئت عبر هذا أثناء البحث عن هذا على جوجل لذلك أنا أدرك أنا ارتطام قديم آخر.ومع ذلك GetCustomAttributes يتطلب اثنين params.

typeof(Foo).GetFields(BindingFlags.NonPublic | BindingFlags.Instance)
.Where(x => x.GetCustomAttributes(typeof(SomeAttribute), false).Length > 0);

المعلمة الثانية تحدد ما إذا كنت ترغب في البحث في الميراث الهرمي

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