2011-12-12 23 views
5

Tôi có một ứng dụng máy chủ dựa trên plugin. Cài đặt của nó được mô tả dưới dạng hợp đồng dữ liệu:Hợp đồng dữ liệu: Bỏ qua các loại không xác định trên deserialization

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

Bất kỳ plugin nào có loại cài đặt riêng. E. G .:

[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; } 
} 

Tại thời gian chạy, người dùng đã cấu hình máy chủ và các plugin như vậy một cách:

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

Sau đó, ứng dụng của tôi đã cứu mình thông qua DataContractSerializer. Các loại trình cắm đã được chuyển thành các kiểu đã biết cho hàm tạo của trình nối tiếp.

Câu hỏi.
Người dùng loại bỏ lắp ráp vật lý bằng "Plugin2" và sau đó khởi động ứng dụng của tôi.
Vì vậy, khi máy chủ nhận được danh sách các plugin có sẵn, nó không biết gì về phiên bản "Plugin2Setup" được tuần tự hóa.

Tôi muốn bỏ qua trường hợp này và cho phép người dùng làm việc mà không cần cài đặt "Plugin2".
Có cách nào thanh lịch để thực hiện việc này không?
Tôi có thể lưu trữ các thiết lập plugin như hợp đồng dữ liệu tuần tự thành chuỗi:

public ObservableCollection<String> PluginSetups 

nhưng nó không tiện dụng và xấu xí.

Chỉnh sửa 1
Vấn đề là làm thế nào để deserialize trường hợp HostSetup và bỏ qua trường hợp Plugin2Setup được nối tiếp.

Chỉnh sửa 2
giải pháp hiện tại của tôi là:

[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; 
} 

Có thể đó là khủng khiếp, nhưng nó hoạt động. :)

Trả lời

0

Tôi nghĩ lý tưởng bạn nên có một cái gì đó trên dòng

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

và khi bạn áp dụng tải trọng bạn nên khởi obj.PluginSetups sử dụng phản ánh dựa trên MyPluginCustomAttribute vì vậy chỉ lắp ráp có mặt có các loại của họ đăng ký. Vì vậy, bạn sẽ không có vấn đề thiếu hội đồng. Bạn cũng có thể sử dụng Managed Extensibility Framework (MEF) thay vì của riêng bạn MyPluginCustomAttribute

+0

Câu hỏi không phải là "cách nhận danh sách các plugin sẵn có và loại cài đặt của chúng" hoặc "cách khởi chạy cài đặt plugin". Vấn đề là deserialization của đồ thị đối tượng có chứa các loại không rõ. – Dennis

Các vấn đề liên quan