2013-01-14 83 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的大小(可能相当大,因为给定引用的深度)。