2010-02-24 17 views
10

मैं डीई के रूप में कार्यान्वयन वर्ग में इंटरफेस को मैप करने के लिए एमईएफ का उपयोग करता हूं। उदाहरण के लिए, मैं एक इंटरफ़ेस के लिए आयात विशेषता का उपयोग करता हूं, और कार्यान्वयन कक्षा के लिए निर्यात करता हूं। मेरी समझ यह है कि एमईएफ ढांचा कार्यान्वयन कक्षा के उदाहरण बनाएगा और उन्हें उपयोग या ऑटो इंजेक्शन के लिए एमईएफ के कंटेनर में रखेगा।MEF कंटेनर द्वारा घटकों का निपटान करें?

मेरे कुछ कार्यान्वयन वर्ग IDISpose इंटरफ़ेस को लागू करते हैं। चूंकि एमईएफ द्वारा उदाहरण बनाए गए हैं, मुझे लगता है कि एमईएफ बाहर होने पर मुझे डिस्पोजेबल होने पर एमईएफ को घटकों को निपटाने के लिए कहा जाना चाहिए। उदाहरण के लिए, मेरे आवेदन में, मैं एमईएफ के कंटेनर का संदर्भ रखता हूं। जब आवेदन समाप्त हो जाता है, तो मैं कंटेनर की निपटान विधि को कॉल करता हूं। समस्या यह है कि मेरे घटकों का निपटान कभी नहीं कहा जाता है। समान तरीके से अन्य मैपिंग के लिए

[Import] 
private IMyInterface IComponent1 { get; set; } 
.... 

[Export] 
private IMyInterface Component { 
    get { 
    var instance = new MyImplemetation(); 
    .... 
    return instance; 
} 
} 
.... 

कई अन्य आयात और निर्यात परिभाषाएँ:

यहाँ आयात और निर्यात मानचित्रण के बारे में कुछ उदाहरण कोड है। मैं इस तरह से मैपिंग का निर्माण करता हूं ताकि एमईएफ के संबंधों का ज्ञान हो और मैप किए गए उदाहरण कैसे बनाएं।

var catalog = new AggregateCatalog(); 
catalog.Add (new AssemblyCatalog(Assembly.GetExecutingAssembly()); 
var batch = new CompositionBatch(); 
batch.AddPart(catalog); 
// MEF container has all the mappings 
var container = new CompositionContainer(catalog); 
.... 
// Get instance from container 
var instance = container.GetExportedValue<IMyInterface>(); 
// my instance CTOR has a contructor with several other 
// implementation instances injected by interface 
// instance starts to do its job and coordinates others ... 
instance.Start(); 
.... 
// Finally the job is done. 
// Dispose the container explicitly there. 
container.Dispose(); 
// But my components are never disposed 
// this results some connections not being closed 
// file streams not being closed... 

यहाँ उदाहरण कई अन्य घटकों MEF द्वारा ctor के माध्यम से इंजेक्शन है: यहाँ अपने आवेदन में कुछ कोड AssemblyCatalog का उपयोग करके मैपिंग लोड करने के लिए कर रहे हैं। उन घटकों में अन्य घटक भी होते हैं जिन्हें एमईएफ द्वारा इंजेक्शन दिया जाता है। समस्या यह है कि कुछ उदाहरण साझा किए जाने के बाद घटकों को निपटाने के लिए निर्णय करना वाकई मुश्किल है। अगर मैंने एक पर निपटान कहा है, तो इससे दूसरों को इसका उपयोग करने में सक्षम नहीं होगा। जैसा कि आप इस तस्वीर में देख सकते हैं, एमईएफ द्वारा उदाहरण बनाए जाते हैं और मेरे आवेदन कक्षाओं में इंजेक्शन दिए जाते हैं। प्रत्येक घटक को दूसरों का कोई ज्ञान नहीं होना चाहिए, और इसे नौकरी करने के लिए इंजेक्शन घटकों का उपयोग करना चाहिए।

मुझे यकीन नहीं है कि कॉल करने के लिए एमईएफ को कहां/कैसे निर्देशित किया जाना चाहिए जब आवेदन समाप्त हो जाता है या कंटेनर का निपटारा किया जाता है? क्या मुझे घटकों पर निपटान करना चाहिए? मुझे नहीं लगता कि यह सही है क्योंकि एमईएफ उन्हें बनाता है और उन्हें आवश्यकतानुसार ग्राहकों में इंजेक्ट करता है। ग्राहकों को अपनी नौकरियों को खत्म करते समय अपना निपटान नहीं करना चाहिए।

उत्तर

7

MEF यह घटकों के जीवनकाल का प्रबंधन करता है। ऐसा लगता है कि आपके उदाहरण में समस्या यह है कि जिस वस्तु को आप निपटाना चाहते हैं वह वास्तव में एमईएफ द्वारा नहीं बनाया गया है। शायद आप इस तरह कुछ करना चाहता हूँ:

public class ComponentExporter : IDisposable 
{ 
    private IMyInterface _component; 

    [Export] 
    public IMyInterface Component 
    { 
     get 
     { 
      if (_component != null) 
      { 
       _component = new MyImplementation(); 

       // ... 
      } 
      return _component; 
     } 
    } 

    public void Dispose() 
    { 
     if (_component != null) 
     { 
      _component.Dispose(); 
     } 
    } 
} 

ComponentExporter कक्षा वास्तव में MEF द्वारा बनाई है, और अगर यह IDisposable लागू करता तो MEF कंटेनर साथ यह निपटाने होंगे। इस उदाहरण में ComponentExporter जब यह निपटान होता है तब बनाए गए घटक को डिस्प्ले करता है, जो संभवतः आप चाहते हैं।

बेशक यह आसान होगा अगर आप सीधे MyImplementation क्लास पर निर्यात डाल दें। मैं आपको लगता है कि नहीं करने के लिए किसी कारण है मान लेते हैं, लेकिन यह है कि यह कैसे लगेगा है:

[Export(typeof(IMyInterface))] 
public class MyImplementation : IMyInterface, IDisposable 
{ 
    // ... 
} 

एक अपने कोड पर कुछ अन्य नोट: आप शायद बैच के माध्यम से कंटेनर के लिए सूची में जोड़ने के लिए की जरूरत नहीं है , जब तक कि आप इसे कहीं भी आयात नहीं कर रहे हैं और इसे कंटेनर के अंदर भागों से संशोधित कर रहे हैं। और यदि आप कई अनुरोधों को संसाधित करते हैं और प्रदर्शन के बारे में चिंतित हैं, तो आपको केवल एक बार विधानसभा सूची बनाना चाहिए, और फिर सभी अनुरोधों के लिए उसी का उपयोग करना चाहिए।

+0

मुझे लगता है कि डैनियल ने इसे अच्छी तरह से समझाया। मैंने अपनी निर्यात संपत्ति गेटटर में उदाहरण बनाया था। यह घटना को पकड़ने और वहां से साफ करने के लिए समझ में आता है। मैं कक्षा के बजाय गेटटर पर निर्यात करना पसंद करता हूं। मैं इसका परीक्षण करूंगा और आपको बता दूंगा कि इससे समस्या हल हो जाएगी या नहीं। –

1

डैनियल सही है। मैंने अपने मैपिंग कक्षाओं में गुणों के रूप में आयात और निर्यात के संबंधों को परिभाषित किया। मैंने उन्हें एमईएफ के कंटेनर में कंपोज़ेबलपार्ट कैटलॉग के रूप में लोड किया ताकि एमईएफ जादुई रूप से फ्लाई पर इसी तरह के उदाहरण ला सके।यह मैपिंग कक्षाओं के भीतर है कि मेरे पास नए उदाहरणों के लिए कुछ कोड हैं। इसलिए, एमईएफ प्रक्रिया के बाहर होने पर बनाए गए संसाधनों का निपटान करने के लिए एमईएफ को उन मानचित्रण वर्गों पर वापस कॉल करने का तरीका ढूंढना है।

मुझे डैनियल के सुझाव को मेरे निर्यात भाग के लिए कक्षा शुरू करने के लिए पसंद है।

public class ComponentExporterBase: IDisposable { 
    private List<IDisposable> _list; 

    public ComponentExporterBase() { 
    _list = new List<IDisposable>(); 
    } 

    protect void Add(IDisposable obj) { 
    _list.Add(obj); 
    } 

    protected virtual void Dispose(bool disposing) { 
    if (disposing) { 
     foreach(var obj in _list) { 
     obj.Dispose(); 
     } 
     _list.Clear(); 
    } 
    } 

    public void Dispose() { 
    Dispose(true); 
    } 
} 
इस आधार वर्ग के साथ

, मेरे मानचित्रण कक्षाएं MEF करने के लिए जाने के लिए सक्षम हो जाएगा: चूंकि मेरे सारे डि मैपिंग गुण (गेटर और setters) के रास्ते में परिभाषित कर रहे हैं, मैं इस तरह एक आधार वर्ग बनाया नौकरी का निपटान उदाहरण के लिए, यहां एक उदाहरण है:

internal class MyDIMappingClass : ComponentExporterBase { 
    [Import] 
    private IDataReader _dataReader { get; set; } 

    [Export] 
    private IController { 
     get { 
     var reader = _dataReader; 
     var instance = new MyMainController(reader); 
     base.Add(instance); 
     return instance; 
    } 
    ... 
} 

मेरे सभी मानचित्रण वर्गों को इसी तरह परिभाषित किया गया है, और वे बहुत साफ हैं। मूलभूत सिद्धांत यह है कि किसी वर्ग के भीतर बनाए गए उदाहरण या संसाधन कक्षा के भीतर निपटाए जाने चाहिए, लेकिन इंजेक्शन वाले उदाहरण नहीं। इस तरह, मैं, किसी भी अधिक MEF द्वारा किसी भी इंजेक्शन उदाहरणों साफ करने के लिए इस उदाहरण में की जरूरत नहीं है:

public class MyMainController : IController { 
    private IDataReader _dataReader; 

    // dataReader is injected through CTOR 
    public MyMainControler(IDataReader dataReader) { 
    _dataReader = dataReader; 
    ... 
    } 
    ... 
    public void Dispose() { 
    // dispose only resources created in this class 
    // _dataReader is not disposed here or within the class! 
    ...} 
} 

वैसे, मैं अपने आयात और निर्यात के रूप में गुण का उपयोग करने के बाद से गुण की तरह कक्षा 'व्यापार तर्क करने के लिए कुछ भी नहीं। अन्य कई मामलों में, कुछ वर्ग तीसरे पक्ष से हैं और मेरे पास निर्यात के रूप में चिह्नित करने के लिए उनके स्रोत कोड तक पहुंच नहीं है।

संबंधित मुद्दे