it-swarm-tr.com

Reflection ile özel bir alan mı buluyorsunuz?

Bu sınıfa verilen

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

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

Bir öznitelikle işaretleyeceğim özel öğeyi _bar bulmak istiyorum. Mümkün mü?

Bunu bir özellik aradığım özelliklerle yaptım ancak hiçbir zaman özel üye alanı olmadı.

Özel alanları elde etmek için ayarlamam gereken bağlayıcı bayraklar nelerdir?

208
David Basarab

BindingFlags.NonPublic ve BindingFlags.Instance bayraklarını kullanın

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

Aynen bir özellik gibi yapabilirsiniz:

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

Reflection kullanarak özel değişkenin değerini al:

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

Reflection kullanarak özel değişken için değer ayarlayın:

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

ObjectForFooClass, Foo sınıfı için boş olmayan bir örnek olduğunda.

37
Suriya

Özel üyelere yansırken dikkat etmeniz gereken bir şey, uygulamanızın orta düzeyde güven içinde (örneğin, paylaşılan bir barındırma ortamında çalışırken), onları bulmayacak olmasıdır. BindingFlags.NonPublic seçeneği sadece göz ardı edilir.

24
jammycakes
typeof(MyType).GetField("fieldName", BindingFlags.NonPublic | BindingFlags.Instance)
18
Darren Kopp

Uzatma Yöntemi İle Güzel Sözdizimi

İsteğe bağlı türdeki herhangi bir özel alana aşağıdaki kodla erişebilirsiniz:

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

Bunun için işi sizin için yapacak bir uzatma yöntemi tanımlamanız gerekir:

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);
    }
}
11
Bruno Zell

Bu yöntemi şahsen kullanırım

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

Basit alma ve ayarlama özel alanlar ve özellikleri için bazı uzatma yöntemleri:

kullanım örneği:

    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

Kod:

    /// <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;
        }
    }
4
epsi1on

Evet, ancak ciltleme bayraklarınızı özel alanlar aramaya ayarlamanız gerekir (eğer sınıf örneğinin dışındaki üyeyi arıyorsanız).

İhtiyacınız olacak bağlayıcı bayrak: System.Reflection.BindingFlags.NonPublic

4
mmattax

Bunu Google’da arama yaparken karşılaştım, bu yüzden eski bir yazıya çarptığımı fark ediyorum. Ancak GetCustomAttributes iki param gerektirir.

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

İkinci parametre, miras hiyerarşisini aramak isteyip istemediğinizi belirtir

2
Gunner