2011-12-12 15 views
5

मेरे पास एक प्लगइन-आधारित होस्ट एप्लिकेशन है। इसकी सेटिंग्स को डेटा अनुबंध के रूप में वर्णित किया गया है:डेटा अनुबंध: deserialization पर अज्ञात प्रकारों को अनदेखा करें

[DataContract(IsReference = true)] 
public class HostSetup 
{ 
    [DataMember] 
    public ObservableCollection<Object> PluginSetups 
    { 
     get 
     { 
      return pluginSetups ?? (pluginSetups = new ObservableCollection<Object>()); 
     } 
    } 
    private ObservableCollection<Object> pluginSetups;   
} 

किसी भी प्लगइन की अपनी सेटिंग्स का प्रकार होता है। ई जी .:

[DataContract(IsReference = true)] 
public class Plugin1Setup 
{ 
    [DataMember] 
    public String Name { get; set; } 
} 

और

[DataContract(IsReference = true)] 
public class Plugin2Setup 
{ 
    [DataMember] 
    public Int32 Percent { get; set; } 
    [DataMember] 
    public Decimal Amount { get; set; } 
} 

रन-टाइम में उपयोगकर्ता को कॉन्फ़िगर किया मेजबान और प्लग इन को इस तरह से:

 var obj = new HostSetup(); 
     obj.PluginSetups.Add(new Plugin1Setup { Name = "Foo" }); 
     obj.PluginSetups.Add(new Plugin2Setup { Percent = 3, Amount = 120.50M }); 

फिर, अपने आवेदन बचाया है अपनी DataContractSerializer के माध्यम से सेटिंग्स। प्लगइन प्रकार serializer के कन्स्ट्रक्टर के लिए ज्ञात प्रकार के रूप में पारित किया गया था।

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

मैं इस उदाहरण को अनदेखा करना चाहता हूं, और उपयोगकर्ता को "प्लगइन 2" सेटिंग्स के बिना काम करने देना चाहता हूं।
क्या ऐसा करने के लिए कोई शानदार तरीका है?
मैं के रूप में डेटा अनुबंध तार में धारावाहिक प्लग इन 'सेटिंग्स को संग्रहीत कर सकते हैं:

public ObservableCollection<String> PluginSetups 

लेकिन यह काम और बदसूरत नहीं है।

संपादित करें 1
समस्या उदाहरण HostSetup deserialize और धारावाहिक Plugin2Setup उदाहरण अनदेखी करने के लिए कैसे है।

संपादित 2
मेरे वर्तमान समाधान है:

[DataContract(IsReference = true)] 
public class PluginSetupContainer 
{ 
    [DataMember] 
    private String typeName; 
    [DataMember] 
    private String rawData; 

    [OnSerializing] 
    private void OnSerializing(StreamingContext context) 
    { 
     if (SetupParameters != null) 
     { 
      using (var writer = new StringWriter()) 
      using (var xmlWriter = new XmlTextWriter(writer)) 
      { 
       var setupParametersType = SetupParameters.GetType(); 
       var serializer = new DataContractSerializer(setupParametersType); 
       serializer.WriteObject(xmlWriter, SetupParameters); 

       xmlWriter.Flush(); 

       typeName = setupParametersType.AssemblyQualifiedName; 
       rawData = writer.ToString(); 
      } 
     } 
    } 

    [OnSerialized] 
    private void OnSerialized(StreamingContext context) 
    { 
     ClearInternalData(); 
    } 

    [OnDeserialized] 
    private void OnDeserialized(StreamingContext context) 
    { 
     if (!String.IsNullOrEmpty(typeName) && !String.IsNullOrEmpty(rawData)) 
     { 
      var setupParametersType = Type.GetType(typeName, false); 
      if (setupParametersType != null) 
      { 
       using (var reader = new StringReader(rawData)) 
       using (var xmlReader = new XmlTextReader(reader)) 
       { 
        var serializer = new DataContractSerializer(setupParametersType); 
        SetupParameters = serializer.ReadObject(xmlReader); 
       } 
      } 

      ClearInternalData(); 
     } 
    } 

    private void ClearInternalData() 
    { 
     typeName = null; 
     rawData = null; 
    } 

    public Object SetupParameters { get; set; } 
} 

[DataContract(IsReference = true)] 
public class HostSetup 
{ 
    [DataMember] 
    public ObservableCollection<PluginSetupContainer> PluginSetups 
    { 
     get 
     { 
      return pluginSetups ?? (pluginSetups = new ObservableCollection<PluginSetupContainer>()); 
     } 
    } 
    private ObservableCollection<PluginSetupContainer> pluginSetups; 
} 

हो सकता है यह भयानक है, लेकिन यह काम करता है। :)

उत्तर

0

मैं आदर्श रूप लगता है कि आप

[DataContract(IsReference = true)] 
[MyPluginCustomAttribute] 
public class Plugin1Setup 
{ 
} 

की तर्ज पर कुछ करना चाहिए था और जब आप आवेदन भार आप obj.PluginSetups प्रारंभ MyPluginCustomAttribute इसलिए केवल विधानसभाओं कि मौजूद हैं के आधार पर प्रतिबिंब का उपयोग करना चाहिए उनके प्रकार पंजीकृत किया है। तो आपको असेंबली गायब होने की समस्या नहीं होगी। आप अपना स्वयं का MyPluginCustomAttribute

+0

सवाल का Managed Extensibility Framework (MEF) उपयोग कर सकते हैं बजाय "कैसे उपलब्ध प्लगइन्स और उनकी सेटिंग प्रकार की एक सूची प्राप्त करने के लिए" नहीं है या "कैसे प्लगइन सेटिंग्स को प्रारंभ करने के लिए"। समस्या अज्ञात प्रकार वाले ऑब्जेक्ट ग्राफ़ का deserialization है। – Dennis

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