هل هناك طريقة أستطيع فرض طريقة اتباع طريقة معينة التوقيع ؟

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

سؤال

دعونا نقول لدي

public delegate DataSet AutoCompleteDelegate(
      string filter, long rowOffset);

يمكن جعل الطبقة التالية لتطبيق هذا الأسلوب التوقيع ؟ (مجرد استحضرت فكرة):

public class MiddleTier
{
    [Follow(AutoCompleteDelegate)]
    public DataSet Customer_AutoComplete(string filter, long rowOffset)
    {
        var c = Connect();
        // some code here
    }

    [Follow(AutoCompleteDelegate)]
    public DataSet Item_AutoComplete(string filter, long rowOffset)
    {
        var c = Connect();
        // some code here
    }



    // this should give compilation error, doesn't follow method signature
    [Follow(AutoCompleteDelegate)]
    public DataSet BranchOffice_AutoComplete(string filter, string rowOffset)
    {
        var c = Connect();
        // some code here
    }         

}

[عدل]

الغرض:لقد وضعت بالفعل سمات في middletier أساليب.لدي طرق مثل هذا:

public abstract class MiddleTier : MarshalByRefObject
{
    // Operation.Save is just an enum

    [Task("Invoice", Operation.Save)]
    public Invoice_Save(object pk, DataSet delta);

    [Task("Receipt", Operation.Save)]
    public Receipt_Save(object pk, DataSet delta);


    // compiler cannot flag if someone deviates from team's standard
    [Task("Receipt", Operation.Save)]
    public Receipt_Save(object pk, object[] delta); 
}

ثم في وقت التشغيل ، سوف تكرار كل middletier أساليب ووضعها على جمع(سمات يساعد كثيرا هنا) ، ثم تعيين لهم على winform مندوب وظائف(يسر واجهة الإضافات على أساس النظام) مثل تحميل

أنا أفكر إذا أنا يمكن أن تجعل من الصفات الذاتية التي تصف ذلك المترجم يمكن التقاط التناقضات.

namespace Craft
{        
    // public delegate DataSet SaveDelegate(object pk, DataSet delta); // defined in TaskAttribute

    public abstract class MiddleTier : MarshalByRefObject
    {

        [Task("Invoice", SaveDelegate)]        
        public abstract Invoice_Save(object pk, DataSet delta);

        [Task("Receipt", SaveDelegate)]
        // it's nice if the compiler can flag an error
        public abstract Receipt_Save(object pk, object[] delta);
    }
}

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

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

المحلول

يمكنك تنفيذ FollowAttribute يمكنك استخدامها في المثال الخاص بك ، كتابة تحليل ثابت (مثلا ، FxCop) القاعدة التي يمكن أن تحقق إذا كان أي الأسلوب الذي هو معلم مع أن السمة نفس التوقيع كما ذكر مندوب.لذلك ينبغي أن يكون من الممكن.

نصائح أخرى

إجابات أخرى الواضح صالحة ولكن لا شيء من شأنها حماية لك ضد النسيان تطبيق [Follow(AutoCompleteDelegate)] السمة على الأسلوب الخاص بك.

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

public interface IAutoComplete
{
    DataSet Complete(string filter, long rowOffset);
}

public class CustomerAutoComplele : IAutoComplete
{
    public DataSet Complete(string filter, long rowOffset)
    {
        var c = Connect();
        // some code here
    }
}

ومن ثم استخدام مصنع نمط طريقة الحصول على الخاص بك "السيارات completers":

public static class AutoCompleteFactory
{
    public static IAutoComplete CreateFor(string purpose)
    {
        // build up and return an IAutoComplete implementation based on purpose.
    }
}

أو

public static class AutoCompleteFactory
{
    public static IAutoComplete CreateFor<T>()
    {
        // build up and return an IAutoComplete implementation based on T which
        // could be Customer, Item, BranchOffice class.
    }
}

وبمجرد الانتهاء من ذلك يمكنك إلقاء نظرة على انعكاس السيطرة والتبعية الحقن لتجنب الثابت ترميز قائمة الإكمال التلقائي تطبيقات في المصنع الخاص بك طريقة.

هذه ليست لغة الميزة, ولكن...

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

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

أود السؤال لماذا تريد أن تفعل هذا.إذا كنت لا تريد الطبقة إلى تغيير من خلال الميراث يمكنك جعله يختم الدرجة.إذا كنت قلقا حول شخص ما تغيير الدرجة في المستقبل لديك 1 من حالتين.1) أنهم لا يفهمون ما يقومون به ؛ لا شيء يمكن أن يمنع سوء مبرمج من فعل أشياء سيئة إذا كان لديهم كامل عهد إلى تحرير برنامج نصي.2) أنهم توسيع وظائف الفئة بطريقة لا نفهم حاليا وهو ما يضر إعادة استخدامها.

سمات يتم تخزين اضافية المعلومات الوصفية خلال ترجمة - يمكنك الاستعلام لهم في وقت التشغيل ولكن خلال تجميع أنها ليست في الحسبان.

لا يمكنك تقييد الطريقة سمة على ذلك.يمكنك تقييد كيف يتم تطبيق السمة (أيفقط على الطرق ، أو ما إذا كان أكثر من واحد يمكن تطبيقها).

أود أن أقترح استخدام FxCop أن نحذر عندما سمات لا تتطابق - إذا كنت لا كن حذرا من الأحداث نوع الدعم يلقي:

[Follow(AutoCompleteDelegate)]
public DataSet Customer_AutoComplete(string filter, int rowOffset)

سيكون من صالح مندوب.

لا.

نوعا ما.

لا يمكنك الحصول على هذا السلوك في وقت الترجمة.يمكنك مع سمات يشق هذا اختبار بسيط تسخير أو القوة فوري الفشل عندما تحتوي الطبقة مثيل.

النظر في اثنين (بسرعة اختراق) سمات:

[AttributeUsage(AttributeTargets.Class)]
public class EnforceConforms : Attribute
{
    public EnforceConforms(Type myClass)
        : base()
    {
        MethodInfo[] info = myClass.GetMethods();

        foreach (MethodInfo method in info)
        {
            object[] objs = method.GetCustomAttributes(false);

            foreach (object o in objs)
            {
                Attribute t = (Attribute)o;

                if (t.GetType() != typeof(ConformsAttribute)) continue;

                MethodInfo mustConformTo = ((ConformsAttribute)t).ConformTo;

                ParameterInfo[] info1 = mustConformTo.GetParameters();
                ParameterInfo[] info2 = method.GetParameters();

                bool doesNotCoform = false;

                doesNotCoform |= (mustConformTo.ReturnType != method.ReturnType);
                doesNotCoform |= (info1.Length != info2.Length);

                if (!doesNotCoform)
                {
                    for (int i = 0; i < info1.Length; i++)
                    {
                        ParameterInfo p1 = info1[i];
                        ParameterInfo p2 = info2[i];

                        if (!p1.ParameterType.Equals(p2.ParameterType))
                        {
                            doesNotCoform = true;
                            break;
                        }
                    }
                }

                if (doesNotCoform)
                {
                    throw new Exception(myClass.Name + "." + method.Name + " does not conform to required delegate signature");
                }
            }
        }
    }
}

[AttributeUsage(AttributeTargets.Method)]
public class ConformsAttribute : Attribute
{
    public MethodInfo ConformTo;

    public ConformsAttribute(Type type)
        : base()
    {
        if (type.BaseType != typeof(Delegate) && type.BaseType != typeof(System.MulticastDelegate)) throw new Exception("Can only accept delegates");

        ConformTo = type.GetMethod("Invoke");
    }
}

رمي EnforceConforms(typeof(myFavoriteClass)) على فئة ، ويتفق مع(typeof(myFavoriteDelegate)) على صلة أساليب ثم (هذا هو hacky جزء) تشير typeof(myFavoriteClass).GetCustomAttributes(كاذبة).يمكنك أن تفعل ذلك في ثابت مهيئ من أن تفشل "بسرعة" أو في فئة اختبار (الذي يبحث عن كل الطرق في الجمعية مع EnforceConforms السمة إذا كنت ترغب في الحصول على الهوى).

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

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