سؤال

لدي كائن يقوم بتنفيذ IDisposable ومسجل في Windsor Container وأرغب في التخلص منه بحيث يتم استدعاء طريقة التخلص الخاصة به وفي المرة التالية التي يتم فيها استدعاء Resolve فإنه يجلب مثيلًا جديدًا.

يفعل

container.Release(obj); 

استدعاء Dispose() تلقائيًا على الفور؟أو هل أحتاج إلى القيام به

obj.Dispose();
container.Release(obj);

لم أتمكن من العثور على أي شيء في الوثائق حول ما يفعله الإصدار بالضبط

يحرر:انظر إجابتي أدناه للحصول على نتائج الاختبارات التي أجريتها.الآن يصبح السؤال، كيف يمكنني إجبار الحاوية على إطلاق مثيل لمكون بدورة حياة مفردة؟يجب أن يتم ذلك في مكان واحد فقط، وكتابة دورة حياة مخصصة تبدو ثقيلة جدًا، أليس هناك طريقة مدمجة للقيام بذلك؟

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

المحلول

أعتقد أن هذا شيء لا يدركه الناس حقًا عند العمل مع حاوية وندسور - خاصة في كثير من الأحيان مفاجئ السلوك الذي يتم من خلاله الاحتفاظ بالمكونات المؤقتة التي يمكن التخلص منها بواسطة الحاوية طوال عمر النواة حتى يتم التخلص منها ما لم تقم بتحريرها بنفسك - على الرغم من توثيقها - ألقِ نظرة هنا - ولكن على الاقتباس بسرعة:

لدى Microkernel سياسة إطلاق قابلة للتوصيل يمكنها توصيل وتنفيذ بعض التوجيه للتخلص من المكونات.يأتي MicroKernel مزودًا بثلاثة تطبيقات IReleasePolicy:

  • سياسة إصدار كافة المكونات:تتبع جميع المكونات لفرض التخلص الصحيح عند التخلص من مثيل MicroKernel
  • سياسة إصدار مكونات دورة الحياة:تتبع فقط المكونات المرتبطة بدورة حياة الخروج من الخدمة
  • سياسة عدم التتبع:لا يقوم بأي تتبع

يمكنك أيضًا تنفيذ سياسة الإصدار الخاصة بك باستخدام الواجهة IReleasePolicy.

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

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

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

نصائح أخرى

يعتمد ذلك على نمط حياة المكون الذي حددته عند إضافته إلى الحاوية.

يمكنك استخدام Release() إذا كان نمط الحياة مجمّعًا.يؤدي هذا إلى إعادة المكون إلى المجموعة لعملية الاسترداد التالية (لم يتم إتلاف الكائن، لذا سيكون التخلص منه أمرًا سيئًا)

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

إذا كان نمط الحياة هو الخيط، فسيتم استخدام نفس المكون لكل خيط، ولا يتم إتلافه.

إذا كان نمط الحياة مفردًا، فسيتم إنشاء مكون واحد فقط وعدم تدميره.

على الأرجح، كنت تستخدم مكونات عابرة؟(إذا كنت قلقًا بشأن التخلص منها في الوقت المناسب) في هذه الحالة ، فما عليك سوى لفه باستخدام استخدام (أو استدعاء نفسك في مكان ما)

using(ISomeService service = container.Resolve<ISomeService>())
{
 // Do stuff here
 // service.Dispose is automatically called 
}

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

حسنًا، لقد قمت بإجراء الاختبارات ويبدو أن الأمر كذلك Container.Release() سوف يتسبب ضمنيًا في ظهور IDisposable Dispose() طريقة للتنفيذ فقط إذا كان نمط الحياة عابرًا (ربما لا يكون هذا صحيحًا تمامًا ولكن النقطة المهمة هي أنه لن يفعل شيئًا رتقًا إذا كان نمط الحياة منفردًا).

الآن إذا اتصلت Container.Dispose() ستستدعي التوابع التي يمكن التخلص منها أيضًا، على الرغم من أنها للأسف ستتخلص من النواة بأكملها وسيتعين عليك إضافة جميع المكونات مرة أخرى:

var container = new WindsorContainer();
container.AddComponentWithLifestyle<MyDisposable>(Castle.Core.LifestyleType.Singleton);
var obj = container.Resolve<MyDisposable>();  // Create a new instance of MyDisposable
obj.DoSomething();
var obj2 = container.Resolve<MyDisposable>();  // Returns the same instance as obj
obj2.DoSomething();
container.Dispose();  // Will call the Disposable method of obj
// Now the components need to be added back in   
 container.AddComponentWithLifestyle<MyDisposable>(Castle.Core.LifestyleType.Singleton);
var obj3 = container.Resolve<MyDisposable>();  // Create a new instance of MyDisposable

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

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