我正在使用DataContractJsonSerializer
来序列化对象图。当我构造这些对象时,每个对象都会接收到一个实用对象实例的引用(它是一个工厂,用于创建抽象合约类的子类的实例) - 这非常有效,直到图形被序列化,然后再次反序列化为止,不再有对实用对象的引用。我需要这个参考。你会如何建议我实现这个(单身不工作,因为单独的图需要他们自己的对象实例)?DataContractJsonSerializer - 为整个图形共享一个对象实例?
0
A
回答
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 static或thread 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
。
相关问题
- 1. 共享一个PrintDocument实例
- 2. 一个JVM中两个JRuby实例之间的共享对象
- 3. 试图从一个共享实例
- 4. 在windows之间共享一个对象实例
- 5. 中的对象的图形替换单一实例对象的多个实例
- 6. 链接到另一个共享对象的共享对象
- 7. 如何在多个操作中共享一个对象的单个实例?
- 8. 对象实例共享子属性?
- 9. 由对象共享的实例变量?
- 10. 的iOS:保留一个共享实例
- 11. 如何与整个项目共享一个对象?
- 12. C#UnitTest跨单元测试共享一个对象的单个实例
- 13. 跨多个vbscript实例共享一个对象(用于ADO连接池)
- 14. 在C#中的多个对象之间共享一个实例化的类
- 15. 实例化一个对象,以便它可以与多个指令共享
- 16. 在哪里保留一个对象实例,我想跨多个ViewModel共享
- 17. 在多个表单之间共享对象实例
- 18. System.NullReferenceException:对象未设置为一个对象的一个实例
- 19. MMAP共享多个对象
- 20. OLE:为多个OLE对象共享IStorage?
- 21. 跨多个对象共享对象实例的最佳方式是什么?
- 22. 共享一个Java对象流
- 23. 如何从一个共享对象
- 24. 一个对象的共享资源
- 25. 从一个对象实例
- 26. 试图为每个对象实例创建一个按钮
- 27. 对象实例化另一个对象?
- 28. 在视图控制器之间共享对象实例
- 29. C++:创建一个共享的对象,而不是共享的对象指针
- 30. MVC 2.0 c#asp.net 4.0从会话中共享的库实例化一个对象