سؤال

لدي فئة بها مجموعة من الخصائص التي تبدو كما يلي:

public string Name
{
    get { return _name; }
    set { IsDirty = true; _name = value; }
}

سيكون الأمر أسهل كثيرًا إذا كان بإمكاني الاعتماد على الإصدار C# 3.0 لإنشاء مخزن دعم لهذه العناصر، ولكن هل هناك أي طريقة لاستبعاد IsDirty=true;حتى أتمكن من كتابة خصائصي بشيء من هذا القبيل وما زلت أحصل على نفس السلوك:

[MakesDirty]
public string Name { get; set; }
هل كانت مفيدة؟

المحلول

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

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

set
{ 
  _name = value; 
  NotifyPropertyChanged("Name"); 
}

إذا كان ذلك ممكنًا، فأنا أعتقد أن هؤلاء الأشخاص الأذكياء في مرض التصلب العصبي المتعدد سيكون لديهم بالفعل شيء من هذا القبيل.

نصائح أخرى

يمكنك محاولة إعداد مقتطف رمز لتسهيل إنشائه.

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

لكن كن حذرًا مع AOP لأنه يمكنك بسهولة إنشاء المزيد من المشكلات باستخدامه والتي تحاول حلها إذا لم يتم استخدامها بشكل صحيح.

هناك المزيد من أطر عمل AOP، بعضها يستخدم التجميع اللاحق وبعضها يستخدم آليات اعتراض الطرق الموجودة في .Net، والأحدث له بعض عيوب الأداء مقارنة بالأول.

لا، عند استخدام الخصائص التلقائية، لا يكون لديك أي سيطرة على التنفيذ.الخيار الأفضل هو استخدام أداة القوالب أو مقتطفات التعليمات البرمجية أو إنشاء SetValue خاص<T>(المرجع T backingField، T value) الذي يغلف منطق الضبط.

private void SetValue<T>(ref T backingField, T value)
{
   if (backingField != value)
   {
      backingField = value;
      IsDirty = true;
   }
}

public string Name
{
   get
   {
      return _name;
   }
   set
   {
      SetValue(ref _name, value);
   }
}

قد يكون البديل الآخر هو منشئ الأكواد مثل صانع الأكواد لأتمتة إنشاء الخصائص.قد يكون هذا مفيدًا بشكل خاص إذا كانت الخصائص التي تقوم بإنشائها عبارة عن أعمدة في جدول قاعدة البيانات

يمكنني أن أوصي باستخدامه مكتبة المؤسسة من اجل ذلك الهدف.توفر كتلة تطبيق السياسة البنية التحتية للقيام "بشيء ما" (شيء = يمكنك ترميز ذلك بنفسك) عندما تدخل/تخرج من طريقة ما على سبيل المثال.يمكنك التحكم في السلوك بالسمات.خذ ذلك كتلميح للخوض في التفاصيل مع وثائق مكتبة المؤسسة.

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

ستحتاج إلى استخدام الانعكاس لتحديد تغييرات الخاصية - وهو ليس كذلك في الواقع الذي - التي باهظة الثمن إلا إذا كنت تفعل الكثير منها!

تنبيه قضائي:لن تتمكن من معرفة ما إذا كانت الخاصية قد تم تغييرها من قيمة غير افتراضية إلى القيمة الافتراضية.

أود أن أقول إن أفضل طريقة لحل هذه المشكلة هي استخدام البرمجة الموجهة نحو الجوانب (AOP).قام ماتس هيلاندر ب اكتب عن هذا على InfoQ.المقال فوضوي بعض الشيء، لكن من الممكن المتابعة.هناك عدد من المنتجات المختلفة التي تستخدم AOP في مساحة .NET، أوصي بـ PostSharp.

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

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

كائن سياقي.إذا قمت بإنشاء فئة تعمل على توسيع كائن مرتبط بالسياق وقمت بإنشاء contextAttribute، فيمكنك اعتراض الاستدعاءات التي تم إجراؤها لهذه الخاصية وتعيين IsDirty.سيقوم .NET بإنشاء وكيل لفصلك الدراسي بحيث تمر جميع المكالمات عبر ما يشبه الحوض البعيد.

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

class A
{
    [Foo]
    public int Property1{get; set;}
    public int Property2{get {return variable;} set{ Property1 = value; variable = value; }
}

عندما يتم استدعاء property1 من فئة أخرى، سيتم استدعاء الوكيل الخاص بك.لكن إذا استدعت فئة أخرى property2، على الرغم من أن مجموعة property2 ستستدعي خاصية 1 فلن يتم استدعاء الوكيل (الوكيل ليس ضروريًا عندما تكون في الفصل نفسه).

هناك الكثير من نماذج التعليمات البرمجية المتاحة لاستخدام contextBoundObjects، فانظر إليها.

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