2016-11-21 41 views
0

我正在使用DataContractJsonSerializer来序列化对象图。当我构造这些对象时,每个对象都会接收到一个实用对象实例的引用(它是一个工厂,用于创建抽象合约类的子类的实例) - 这非常有效,直到图形被序列化,然后再次反序列化为止,不再有对实用对象的引用。我需要这个参考。你会如何建议我实现这个(单身不工作,因为单独的图需要他们自己的对象实例)?DataContractJsonSerializer - 为整个图形共享一个对象实例?

回答

0

完成此操作的一种方法是使用data contract surrogate。使用代理人,您可以在序列化过程中用虚拟存根替换您的“真实”工厂。然后,在反序列化过程中,将假人替换为所需的工厂。

因此,如果您的类看起来是这样的:

public abstract class FactoryBase 
{ 
} 

public class Factory : FactoryBase 
{ 
} 

public interface IHasFactory 
{ 
    FactoryBase Factory { get; } 
} 

[DataContract] 
public abstract class HasFactoryBase : IHasFactory 
{ 
    [DataMember(IsRequired = true)] 
    FactoryBase factory; 

    public FactoryBase Factory { get { return factory; } } 

    public HasFactoryBase(FactoryBase factory) 
    { 
     this.factory = factory; 
    } 
} 

[DataContract] 
public class Foo : HasFactoryBase 
{ 
    public Foo(FactoryBase factory) 
     : base(factory) 
    { 
     this.Bars = new List<Bar>(); 
    } 

    [DataMember] 
    public List<Bar> Bars { get; set; } 
} 

[DataContract] 
public class Bar : HasFactoryBase 
{ 
    public Bar(FactoryBase factory) : base(factory) { } 
} 

您定义IDataContractSurrogate用替代更换的FactoryBase所有出现如下:

public class FactorySurrogateSelector : IDataContractSurrogate 
{ 
    [DataContract] 
    class FactorySurrogate 
    { 
    } 

    readonly FactoryBase factory; 

    public FactorySurrogateSelector(FactoryBase factory) 
    { 
     this.factory = factory; 
    } 

    #region IDataContractSurrogate Members 

    public object GetCustomDataToExport(Type clrType, Type dataContractType) 
    { 
     throw new NotImplementedException(); 
    } 

    public object GetCustomDataToExport(MemberInfo memberInfo, Type dataContractType) 
    { 
     throw new NotImplementedException(); 
    } 

    public Type GetDataContractType(Type type) 
    { 
     if (typeof(FactoryBase).IsAssignableFrom(type)) 
      return typeof(FactorySurrogate); 
     return type; 
    } 

    public object GetDeserializedObject(object obj, Type targetType) 
    { 
     if (obj is FactorySurrogate) 
      return factory; 
     return obj; 
    } 

    public void GetKnownCustomDataTypes(Collection<Type> customDataTypes) 
    { 
     throw new NotImplementedException(); 
    } 

    public object GetObjectToSerialize(object obj, Type targetType) 
    { 
     if (obj is FactoryBase) 
     { 
      return new FactorySurrogate(); 
     } 
     return obj; 
    } 

    public Type GetReferencedTypeOnImport(string typeName, string typeNamespace, object customData) 
    { 
     throw new NotImplementedException(); 
    } 

    public System.CodeDom.CodeTypeDeclaration ProcessImportedType(System.CodeDom.CodeTypeDeclaration typeDeclaration, System.CodeDom.CodeCompileUnit compileUnit) 
    { 
     throw new NotImplementedException(); 
    } 

    #endregion 
} 

然后,序列化和反序列化如下:

var factory = new Factory(); 
var test = new Foo(factory) 
{ 
    Bars = { new Bar(factory) }, 
}; 

var surrogate = new FactorySurrogateSelector(factory); 
var serializer = new DataContractJsonSerializer(test.GetType(), Enumerable.Empty<Type>(), int.MaxValue, false, surrogate, false); 

byte[] json; 
using (var stream = new MemoryStream()) 
{ 
    serializer.WriteObject(stream, test); 
    json = stream.ToArray(); 
} 

Foo test2; 
using (var stream = new MemoryStream(json)) 
{ 
    test2 = (Foo)serializer.ReadObject(stream); 
} 

if (test2.Factory != test.Factory) 
    throw new InvalidOperationException(); 

注意: t期望的工厂直接进入FactorySurrogateSelector的构造函数,然后最终设置在每个包含工厂类型实例的类型中。

产生的JSON的样子:

{ 
    "factory": {}, 
    "Bars": [ 
    { 
     "factory": {} 
    } 
    ] 
} 

一些资历:

  • 你的工厂必须从一些公共基类继承,这里FactoryBase。数据合同序列化器将从永不序列化接口成员,例如, IFactory factory其中IFactory是您的工厂界面,即使有适用的代理商也是如此。

  • 空的"factory": {}对象必须出现在JSON中,以便代理在反序列化期间注入正确的“真实”工厂值。因此[DataMember(IsRequired = true)]

0

另一种方式来完成是引进thread staticthread local工厂对象,然后用它使用[OnDeserializing] callback填充你的类。

因此,如果您定义类型如下:

public interface IFactory 
{ 
} 

public class Factory : IFactory 
{ 
} 

public interface IHasFactory 
{ 
    IFactory Factory { get; } 
} 

[DataContract] 
public abstract class HasFactoryBase : IHasFactory 
{ 
    [ThreadStatic] 
    static IFactory deserializedFactory; 

    static IFactory DeserializedFactory 
    { 
     get 
     { 
      return deserializedFactory; 
     } 
     set 
     { 
      deserializedFactory = value; 
     } 
    } 

    public static IDisposable SetDeserializedFactory(IFactory factory) 
    { 
     return new PushValue<IFactory>(factory,() => DeserializedFactory, val => DeserializedFactory = val); 
    } 

    IFactory factory; 

    public IFactory Factory { get { return factory; } } 

    public HasFactoryBase(IFactory factory) 
    { 
     this.factory = factory; 
    } 

    [OnDeserializing] 
    void OnDeserializing(StreamingContext context) 
    { 
     this.factory = DeserializedFactory; 
    } 
} 

public struct PushValue<T> : IDisposable 
{ 
    Action<T> setValue; 
    T oldValue; 

    public PushValue(T value, Func<T> getValue, Action<T> setValue) 
    { 
     if (getValue == null || setValue == null) 
      throw new ArgumentNullException(); 
     this.setValue = setValue; 
     this.oldValue = getValue(); 
     setValue(value); 
    } 

    #region IDisposable Members 

    // By using a disposable struct we avoid the overhead of allocating and freeing an instance of a finalizable class. 
    public void Dispose() 
    { 
     if (setValue != null) 
      setValue(oldValue); 
    } 

    #endregion 
} 

[DataContract] 
public class Foo : HasFactoryBase 
{ 
    public Foo(IFactory factory) 
     : base(factory) 
    { 
     this.Bars = new List<Bar>(); 
    } 

    [DataMember] 
    public List<Bar> Bars { get; set; } 
} 

[DataContract] 
public class Bar : HasFactoryBase 
{ 
    public Bar(IFactory factory) : base(factory) { } 
} 

可序列化和反序列化如下:

var factory = new Factory(); 
var test = new Foo(factory) 
{ 
    Bars = { new Bar(factory) }, 
}; 

var serializer = new DataContractJsonSerializer(test.GetType()); 

byte [] json; 
using (var stream = new MemoryStream()) 
{ 
    serializer.WriteObject(stream, test); 
    json = stream.ToArray(); 
} 

Foo test2; 
using (HasFactoryBase.SetDeserializedFactory(factory)) 
using (var stream = new MemoryStream(json)) 
{ 
    test2 = (Foo)serializer.ReadObject(stream); 
} 

if (test2.Factory != test.Factory) 
    throw new InvalidOperationException(); 

而且JSON的样子:

{ 
    "Bars": [ 
    {} 
    ] 
} 

一些注意事项:

  • 工厂对象在JSON中完全不出现。

  • 工厂对象不再需要从一些抽象基类继承,它们可以简单地实现一个通用的接口IFactory

相关问题