我正在使用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. 在windows之間共享一個對象實例
- 4. 鏈接到另一個共享對象的共享對象
- 5. 如何在多個操作中共享一個對象的單個實例?
- 6. 對象實例共享子屬性?
- 7. 的iOS:保留一個共享實例
- 8. 如何與整個項目共享一個對象?
- 9. 跨多個vbscript實例共享一個對象(用於ADO連接池)
- 10. C#UnitTest跨單元測試共享一個對象的單個實例
- 11. 在C#中的多個對象之間共享一個實例化的類
- 12. 在哪裏保留一個對象實例,我想跨多個ViewModel共享
- 13. 實例化一個對象,以便它可以與多個指令共享
- 14. System.NullReferenceException:對象未設置爲一個對象的一個實例
- 15. MMAP共享多個對象
- 16. OLE:爲多個OLE對象共享IStorage?
- 17. 一個對象的共享資源
- 18. 跨多個對象共享對象實例的最佳方式是什麼?
- 19. 從一個對象實例
- 20. 試圖爲每個對象實例創建一個按鈕
- 21. 對象實例化另一個對象?
- 22. C++:創建一個共享的對象,而不是共享的對象指針
- 23. 與另一個控件共享屬性的一個實例?
- 24. 讓一個班級的所有實例共享一個值 - Audioclips
- 25. ASMX服務共享單個類實例
- 26. 共享變量的多個ScriptControl實例
- 27. 加載共享庫的兩個實例
- 28. 子實例共享一個共同的superinstance
- 29. 幾個類共享另一個類的實例
- 30. 如何:多個Django實例共享一個全局變量?