2013-01-14 108 views
2

我們試圖序列化一個對象樹。雖然我們取得了成功。我希望找到一種方法來簡化生成的XML。如何刪除DataContractSerializer詳細信息

的物體看起來像下面這樣:

public class RuleSet<T> 
{ 
    public IEnumerable<IState<T>> States { get; set; } 
    public IEnumerable<ICondition<T>> Conditions { get; set; } 
} 

public class State<T> : IState<T> 
{ 
    public string Id { get; set; } 
    public List<ITransition<T>> Transitions { get; set; } 
} 

public class Transition<T> : ITransition<T> 
{ 
    public ICondition<T> Condition { get; set; } 
    public IState<T> Next { get; set; } 
} 

public class Condition<T> : ICondition<T> 
{ 
    public string Id { get; set; } 
    public string Name { get; set; }  
} 

我們用一個非常簡單的序列化代碼的時刻:

public void blah() 
{ 
    var condition1 = new Condition<object>() { 
     Id = "C1", AttributeName = "Foo", ExpectedValue = "Bar" 
    }; 
    var condition2 = new Condition<object>() { 
     Id = "C2", AttributeName = "Bar", ExpectedValue = "Foo" 
    }; 

    var state1Transitions = new List<ITransition<object>>(); 
    var state2Transitions = new List<ITransition<object>>(); 
    var state3Transitions = new List<ITransition<object>>(); 

    var state = new State<object> { 
     Id = "S1", Transitions = state1Transitions 
    }; 
    var state2 = new State<object> { 
     Id = "S2", Transitions = state2Transitions 
    }; 
    var state3 = new State<object> { 
     Id = "S3", Transitions = state3Transitions 
    }; 

    state1Transitions.Add(new Transition<object> { 
     Condition = condition1, Next = state2 
    }); 
    state1Transitions.Add(new Transition<object> { 
     Condition = condition2, Next = state3 
    }); 
    state2Transitions.Add(new Transition<object> { 
     Condition = condition2, Next = state3 
    }); 
    var ruleSet = new RuleSet<object> { 
     States = new List<IState<object>> {state, state2, state3}, 
     Conditions = new List<ICondition<object>>{condition1, condition2} 
    }; 

    var stream1 = new MemoryStream(); 

    var serializer = new DataContractSerializer(typeof(RuleSet<object>), 
     new List<Type> { 
      typeof(State<object>), 
      typeof(Transition<object>), 
     typeof(AttributeEqualTo<object>) 
    }); 

    serializer.WriteObject(stream1, ruleSet); 
    stream1.Position = 0; 

    var xml = new StreamReader(stream1).ReadToEnd(); 
    Console.WriteLine(xml); 
} 

當生成每個級別的輸出的XML完成而不是僅包含對象的引用。基本上每個Transition<T>我們都會爲每個狀態和條件獲得一個完整的對象定義,即使它們是在別處定義的。

有沒有辦法讓那些只是引用?

回答

2

這一切都歸結於你如何創建你的DataContractSerializer

你要打電話the overload of the constructor that allows you to indicate that you will preserve object references,具有以下特徵:

public DataContractSerializer(
    Type type, 
    IEnumerable<Type> knownTypes, 
    int maxItemsInObjectGraph, 
    bool ignoreExtensionDataObject, 
    bool preserveObjectReferences, 
    IDataContractSurrogate dataContractSurrogate 
) 

您可以通過默認值的大部分參數。在你的情況下,調用DataContractSerializer構造函數將是這樣的:

var serializer = new DataContractSerializer(typeof(RuleSet<object>), 
    new [] { 
     typeof(State<object>), 
     typeof(Transition<object>), 
     typeof(AttributeEqualTo<object>) 
    }, 
    Int32.MaxValue, 
    false, 
    /* This is the important flag to set. */ 
    true, 
    null 
); 

注意,從preserveObjectReferences參數文件,它使用非標準的XML(重點煤礦):

preserveObjectReferences

類型:System.Boolean

true至使用非標準XML結構來保留對象引用數據;否則,是錯誤的。

如果您需要.NET以外的其他代碼來解釋這一點,那麼解開引用可能證明是困難的(但不應該是不可能的)。

但是,它可以防止對象圖形自我複製並減小XML的大小(可能相當大,因爲給定引用的深度)。