প্রতিবিম্ব সহ একটি ব্যক্তিগত ক্ষেত্র সন্ধান করবেন?


228

এই ক্লাস দেওয়া

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

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

আমি ব্যক্তিগত আইটেম _ বারটি সন্ধান করতে চাই যা আমি একটি বৈশিষ্ট্যের সাথে চিহ্নিত করব। এটা কি সম্ভব?

আমি এমন বৈশিষ্ট্যগুলির সাথে এটি করেছি যেখানে আমি কোনও বৈশিষ্ট্যের সন্ধান করেছি, তবে কখনও কোনও ব্যক্তিগত সদস্য ক্ষেত্র নেই।

ব্যক্তিগত ক্ষেত্রগুলি পাওয়ার জন্য আমার যে বাঁধাই করা ফ্ল্যাগগুলি প্রয়োজন তা কী?


@ নেসসিও: আপনি কেন এই পদ্ধতিকে গ্রহণ করবেন তার উপর আপনি প্রসারিত করতে পারেন? ...সুবিদাসুমূহ? নাকি সহজ পছন্দ? :)
আইএবস্ট্র্যাক্ট

উত্তর:


279

ব্যবহার BindingFlags.NonPublicএবং BindingFlags.Instanceপতাকা

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

11
আমি কেবল "বাইন্ডিং ফ্ল্যাগস ইনস্ট্যান্স" বাইন্ডিং পতাকা সরবরাহ করে এটি কাজ করতে পারি to
অ্যান্ডি ম্যাকক্ল্যাগেজ

1
আমি আপনার উত্তর স্থির করেছি। এটি অন্যথায় খুব বিভ্রান্তিকর। আবে হাইড্রেব্রাক্টের উত্তর যদিও সবচেয়ে সম্পূর্ণ ছিল।
lubos hasko

2
দুর্দান্ত কাজ করে - এফওয়াইআই ভিবি.এনইটি সংস্করণ মি.গেটটাইপ ()। গেটফিল্ডস (প্রতিচ্ছবি।বাইন্ডিং ফ্ল্যাশস।নোনপাবলিক বা রিফ্লেকশন।বাইন্ডিংফ্লাগস।আইনস্ট্যান্স)
জিজি।

2
উদাহরণস্বরূপ বাইন্ডিং পতাকা ব্যবহার করা কেবলমাত্র যদি আপনি উদাহরণ পদ্ধতিগুলি পেতে চান Using আপনি যদি একটি ব্যক্তিগত স্ট্যাটিক পদ্ধতি পেতে চান তবে আপনি ব্যবহার করতে পারেন (BindingFlags.NonPublic | BindingFlags.Static)
ksun

166

আপনি কোনও সম্পত্তির মতো এটি করতে পারেন:

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

8
চূড়ান্ত নেক্রো-পোস্টিংয়ের জন্য দুঃখিত, তবে এটি আমাকে ফেলে দিয়েছে। গেটকাস্টমঅ্যাট্রিবিউটস (প্রকার) শূন্যটি ফিরে আসবে না যদি বৈশিষ্ট্যটি পাওয়া যায় না, এটি কেবল একটি খালি অ্যারে প্রদান করে।
স্মৃতিভ্রংশ

42

প্রতিবিম্ব ব্যবহার করে ব্যক্তিগত ভেরিয়েবলের মান পান:

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

প্রতিবিম্ব ব্যবহার করে ব্যক্তিগত ভেরিয়েবলের জন্য মান সেট করুন:

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

যেখানে অবজেক্টফোফ্লক্লাস ক্লাস টাইপ ফু-র জন্য একটি নাল উদাহরণ।


অনুরূপ উত্তর ফাংশন ব্যবহার করা সহজ বর্ণনা করে GetInstanceField(typeof(YourClass), instance, "someString") as string কিভাবে সি # তে ব্যক্তিগত ক্ষেত্রের মান পাবেন?
মাইকেল ফ্রেইজিম

24

ব্যক্তিগত সদস্যদের প্রতিফলিত করার সময় আপনার একটি বিষয় সম্পর্কে সচেতন হওয়া দরকার তা হ'ল যদি আপনার অ্যাপ্লিকেশনটি মাঝারি বিশ্বাসে চলতে থাকে (উদাহরণস্বরূপ, যখন আপনি একটি ভাগ্যবান হোস্টিং পরিবেশে চলছেন) তবে এটি তাদের খুঁজে পাবে না - বাইন্ডিংফ্লাগস.নোনপাবলিক বিকল্পটি কেবল এড়ানো হবে।


জ্যামাইক্যাকস আপনি কি ভাগ করে নেওয়া হোস্টিং পরিবেশের উদাহরণ দিতে পারেন? আমি ভাবছি একাধিক অ্যাপ্লিকেশন সহ আইআইএস আপনি কী পাচ্ছেন?
ব্রায়ান সুইভিনে

আমি যেখানে আইআইএসটি মেশিন.কনফিগ স্তরে আংশিক বিশ্বাসের জন্য লক করা আছে সে সম্পর্কে কথা বলছি। আপনি কেবলমাত্র এই দিনগুলিতে কেবল সস্তা এবং কদর্য শেয়ার্ড ওয়েব হোস্টিং পরিকল্পনাগুলিতে এটি খুঁজে পান (যে পছন্দগুলি আমি আর ব্যবহার করি না) - যদি আপনার সার্ভারে আপনার সম্পূর্ণ নিয়ন্ত্রণ থাকে তবে এটি পুরোপুরি বিশ্বাসযোগ্য না কারণ এটি সম্পূর্ণ বিশ্বাস ডিফল্ট.
জ্যামাইকাইক

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

আমি মাঠের নাম জানব না। আমি নামটি ছাড়াই এবং এটিতে যখন বৈশিষ্ট্যটি থাকে এটি সন্ধান করতে চাই।
ডেভিড বাসরব

ক্ষেত্রের নামটি সন্ধান করতে, ভিজ্যুয়াল স্টুডিওতে এটি করা সহজ। ভেরিয়েবলের ব্রেক ব্রেকপয়েন্ট সেট করুন, এর ক্ষেত্রগুলি দেখুন (ব্যক্তিগত সহ সাধারণত এম_ফিল্ডের নাম দিয়ে শুরু করা হয়)। উপরের কমান্ডটিতে সেই m_fieldname প্রতিস্থাপন করুন।
হাও

13

এক্সটেনশন পদ্ধতি সহ দুর্দান্ত সিনট্যাক্স

আপনি এই জাতীয় কোড সহ একটি স্বেচ্ছাচারী ধরণের যে কোনও ব্যক্তিগত ক্ষেত্রে অ্যাক্সেস করতে পারেন:

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);
    }
}

1
বাবু, এটি আমার কোডে এনএলুয়ায় প্রকাশ না করে কোনও সুরক্ষিত পরিবর্তনশীল অ্যাক্সেসের জন্য পারফেক্ট ছিল! অসাধারণ!
tayoung

6

আমি ব্যক্তিগতভাবে এই পদ্ধতিটি ব্যবহার করি

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

6

এখানে সহজ ক্ষেত্র এবং বৈশিষ্ট্যগুলি নির্ধারণের জন্য ব্যক্তিগত ক্ষেত্র এবং বৈশিষ্ট্যগুলি (সেটার সহ বৈশিষ্ট্য) নির্ধারণের জন্য কিছু বর্ধিত পদ্ধতি এখানে রয়েছে:

ব্যবহারের উদাহরণ:

    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;
        }
    }

4

হ্যাঁ, তবে আপনাকে ব্যক্তিগত ক্ষেত্রগুলি অনুসন্ধানের জন্য আপনার বাঁধাই পতাকাগুলি সেট করতে হবে (যদি আপনি শ্রেণীর উদাহরণের বাইরে সদস্যটির সন্ধান করছেন)।

আপনার যে বাঁধাইয়ের পতাকাটি লাগবে তা হ'ল: সিস্টেম.রিফ্লেশন.বাইন্ডিং ফ্ল্যাশস।নোনপাবলিক


2

গুগলে এটি অনুসন্ধান করার সময় আমি এটি পেরিয়ে এসেছি যাতে আমি বুঝতে পারি যে আমি কোনও পুরানো পোস্ট ঠেকছি। তবে গেটকাস্টমঅ্যাট্রিবিউটের জন্য দুটি প্যারাম প্রয়োজন।

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

দ্বিতীয় প্যারামিটারটি উল্লেখ করে যে আপনি উত্তরাধিকারের স্তরক্রম অনুসন্ধান করতে চান কিনা

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.