ما هي أفضل طريقة لمعرفة ما إذا كانت الطريقة هي خاصية من داخل حقن السياسة؟

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

سؤال

لقد تم تطبيق معالج مخصص على فصل دراسي (باستخدام كتلة تطبيق حقن السياسة في entlib 4) وأود أن أعرف ما إذا كانت طريقة الإدخال هي خاصية عند استدعاء الاستدعاء.فيما يلي ما يبدو عليه المعالج الخاص بي.

[ConfigurationElementType(typeof(MyCustomHandlerData))]
public class MyCustomHandler : ICallHandler
{
    public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
    {
        if (input.MethodBase.IsPublic && (input.MethodBase.Name.Contains("get_") || input.MethodBase.Name.Contains("set_")))
        {
            Console.WriteLine("MyCustomHandler Invoke called with input of {0}", input.MethodBase.Name);
        }
        return getNext().Invoke(input, getNext);
    }

    public int Order { get; set; }
}

كما ترون من نموذج التعليمات البرمجية الخاص بي، فإن أفضل طريقة فكرت بها حتى الآن هي تحليل اسم الطريقة.أليس هناك طريقة أفضل للقيام بذلك؟

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

المحلول

يمكنك أيضًا التحقق من صحة IsSpecialName.سيكون هذا صحيحًا في الممتلكات (من بين أشياء أخرى)

على مستوى il، يتم عرض الأساليب على النحو التالي (باستخدام Environment.ExitCode كمثال):

.method public hidebysig specialname static int32 get_ExitCode() cil managed
.method public hidebysig specialname static void set_ExitCode(int32 'value') cil managed

إذا أردت أن تتخيل، يمكنك التحقق بعد استخراج الاسم من وجود العقار المذكور ولكن لنكون صادقين

if (m.IsSpecialName && (m.Attributes & MethodAttributes.HideBySig) != 0)) 

بالإضافة إلى البدء بـ get_ أو set_، فيجب أن تكون جيدًا حتى بالنسبة للأشخاص الذين يستخدمون أسماء سيئة (تزييف Hiddenbysig أمر سهل بما فيه الكفاية، وتزييف IsSpecialName سيكون أمرًا صعبًا للغاية)

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

يبدو لي أن هذا جنون بالنسبة لك على الرغم من أنك لا تتوقع التحايل المتعمد.لن تكون طريقة الأداة المساعدة/الامتداد البسيطة على MethodInfo والتي فعلت هذا المنطق صعبة للغاية، ومن المؤكد تقريبًا أن تضمين IsSpecialName سيغطي جميع احتياجاتك.

نصائح أخرى

يمكنك التحقق من الخاصية IsSpecialName؛سيكون هذا صحيحًا بالنسبة لأصحاب العقارات والمستوطنين.ومع ذلك، سيكون هذا صحيحًا أيضًا بالنسبة للطرق الخاصة الأخرى، مثل التحميل الزائد للمشغل.

لست على دراية بكتلة التطبيق هذه، ولكن بافتراض أن خاصية MethodBase من النوع System.Reflection.MethodBase، يمكنك إلقاء نظرة على خاصية IsSpecialName.

System.Reflection.MethodBase.IsSpecialName على MSDN

ذكر اثنان منكم استخدام خاصية "IsSpecialName" من النوع MethodBase.في حين أنه من الصحيح أن the سيعود صحيحًا بالنسبة للخاصية "gets" أو "sets"، فإنه سيعود أيضًا صحيحًا بالنسبة للتحميلات الزائدة لعامل التشغيل مثل add_EventName أو Remove_EventName.لذلك سوف تحتاج إلى فحص السمات الأخرى لمثيل MethodBase لتحديد ما إذا كان هو أداة الوصول إلى الخاصية.لسوء الحظ، إذا كان كل ما لديك هو إشارة إلى مثيل MethodBase (وهذا ما أعتقد أنه هو الحال مع سلوكيات الاعتراض في إطار عمل Unity) فلا توجد طريقة "نظيفة" حقيقية لتحديد ما إذا كانت أداة ضبط خاصية أو مُحصل عليها.أفضل طريقة وجدتها هي كما يلي:

ج#:

bool IsPropertySetter(MethodBase methodBase){
     return methodBase.IsSpecialName && methodBase.Name.StartsWith("set_");
}

bool IsPropertyGetter(MethodBase methodBase){
     return methodBase.IsSpecialName && methodBase.Name.StartsWith("get_");
}

فب:

 Private Function IsPropertySetter(methodBase As MethodBase) As Boolean

      Return methodBase.IsSpecialName AndAlso methodBase.Name.StartsWith("set_")

 End Function

 Private Function IsPropertyGetter(methodBase As MethodBase) As Boolean

      Return methodBase.IsSpecialName AndAlso methodBase.Name.StartsWith("get_")

 End Function

لقد فات الأوان بعض الشيء ولكن الآخرين سوف يقرأون هذا أيضًا.بالإضافة إلى IsSpecialName والتحقق من البادئة set_ (المشغلون لديهم op_، الحدث subscr./remov.يحتوي على add_,remove_) يمكنك التحقق مما إذا كانت الطريقة مطابقة لأي من طرق الخصائص مثل هذا:

    bool isProperty = method.ReflectedType.GetProperties().FirstOrDefault(p => 
        p.GetGetMethod().GetHashCode() == method.GetHashCode() 
        || p.GetSetMethod().GetHashCode() == method.GetHashCode())!=null;
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top