I've problems to serialize and deserialize a singleton via DataContract.
First some facts:
1.) Singleton is "internal"
2.) Singleton contains Dictionaries
My serialization and deserialization works fine, but it isn't the right way for a singleton. If I deserialize the xml, I always generate a new instance of my singleton and overwrite the current reference of the singleton object - but after this it isn't a singleton further.
Has anybody any idea? - Thanks.
Check this link from msdn, there is an example on serializing a singleton. After deserialization you should return the reference and not the object.
Try using NetDataContractSerializer-
The NetDataContractSerializer differs from the DataContractSerializer
in one important way: the NetDataContractSerializer includes CLR type
information in the serialized XML, whereas the DataContractSerializer
does not. Therefore, the NetDataContractSerializer can be used only if
both the serializing and deserializing ends share the same CLR types.
The serializer can serialize types to which either the
DataContractAttribute or SerializableAttribute attribute has been
applied. It also serializes types that implement ISerializable.
Code example:
[DataContract(Name = "Customer", Namespace = "http://www.contoso.com")]
class Person : IExtensibleDataObject
{
[DataMember()]
public string FirstName;
[DataMember]
public string LastName;
[DataMember()]
public int ID;
public Person(string newfName, string newLName, int newID)
{
FirstName = newfName;
LastName = newLName;
ID = newID;
}
private ExtensionDataObject extensionData_Value;
public ExtensionDataObject ExtensionData
{
get { return extensionData_Value; }
set { extensionData_Value = value; }
}
}
Searialization:
Person p1 = new Person("Zighetti", "Barbara", 101);
FileStream fs = new FileStream(fileName, FileMode.Create);
XmlDictionaryWriter writer = XmlDictionaryWriter.CreateTextWriter(fs);
NetDataContractSerializer ser = new NetDataContractSerializer();
ser.WriteObject(writer, p1);
Msdn Link here
(code for .net 4.0)
I had the same problem:
the de-serialization needs to create a new instance of the singleton class, which it can(!) do because its inside a member function: the constructor is visible to members, but that instance cannot replace the singleton instance visible from the outside (the "this").
So you have to copy the properties from your de-serialized instance into the "this" instance.
Doing the copying by hand gets old fast, so here is my solution using reflection to copy the public writable members that are not marked [xmlignore]:
public static class SerializationHelpers
{
/// <summary>
/// Copy all public props and fields that are not xmlignore
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="target"></param>
/// <param name="other"></param>
public static void CopyTypeFields<T>(T target, T other)
{
// get all public static properties of MyClass type
PropertyInfo[] propertyInfos = other.GetType().GetProperties(BindingFlags.Public
| BindingFlags.Instance);
FieldInfo[] fis = other.GetType().GetFields(BindingFlags.Public |
BindingFlags.Instance);
foreach (FieldInfo fi in fis)
{
if ((fi.Attributes & FieldAttributes.FieldAccessMask) !=
FieldAttributes.Literal &&
(fi.Attributes & FieldAttributes.FieldAccessMask) !=
FieldAttributes.Static)
{
if (IsXmlIgnored(fi)) { continue; }
var myval = fi.GetValue(other);
fi.SetValue(target, myval);
}
}
foreach (PropertyInfo pi in propertyInfos)
{
if (!pi.CanWrite || !pi.CanRead) { continue; }
if (IsXmlIgnored(pi)) { continue; }
var myval = pi.GetValue(other, null);
pi.SetValue(target, myval, null);
}
}
private static bool IsXmlIgnored(MemberInfo pi)
{
object[] fiGetCustomAttributes = pi.GetCustomAttributes(false);
foreach (object ob in fiGetCustomAttributes)
{
if (ob.GetType().
Equals(typeof(System.Xml.Serialization.XmlIgnoreAttribute)))
{
return true;
}
}
return false;
}
}
// to use it ...
// the deserialization method of the singleton mySingleton
public bool loadSingleton()
{
bool ret= false;
try
{
Type myType = GetType();
XmlSerializer reader = new XmlSerializer(myType);
try
{
using (StreamReader file = new StreamReader(filename))
{
try
{
mySingleton t1 = (mySingleton)reader.Deserialize(file);
CopySerializationFields(t1);
ret= true;
}
catch
{
...
}
}
}
catch
{
...
}
}
catch (Exception ex)
{
...
}
return ret;
}
private void CopySerializationFields(ProcessingSettings other)
{
SerializationHelpers.CopyTypeFields(this, other);
}
I just searched quite long for a similar solution for atomic classes and have found an answer to a similar problem by Marc Gravell. This also works for singletons.
In your singleton class you implement the GetRealObject method defined by the interface System.Runtime.Serialization.IObjectReference. There you could also add previously serialized data to the singleton if needed and return the static reference as the reference that is used after deserialization.
Here's my example:
[System.Runtime.Serialization.DataContract]
public class MySingletonClass : System.Runtime.Serialization.IObjectReference
{
private MySingletonClass()
{
}
private static MySingletonClass _Instance;
public static MySingletonClass Instance
{
get
{
if (_Instance == null)
_Instance = new MySingletonClass();
return _Instance;
}
}
object System.Runtime.Serialization.IObjectReference.GetRealObject(System.Runtime.Serialization.StreamingContext context)
{
MySingletonClass realObject = Instance;
realObject.Merge(this);
return realObject;
}
private void Merge(MySingletonClass otherInstance)
{
// do your merging here
}
}
You can use this for atomic classes too. You only have to change the Instance property to a GetInstance method and call it with the appropriate property in the GetRealObject method (i.e. an ID).
[DataContract]
public sealed class SerializableSingletonPattern
{
public static SerializableSingletonPattern Instance { get; private set; } = new SerializableSingletonPattern();
[DataMember] public bool YourData { get; private set; }
// explicit static constructor so C# compiler will not mark type as beforefieldinit
static SerializableSingletonPattern() { }
SerializableSingletonPattern() // your constructor
{
}
[OnDeserialized]
void OnDeserialized(StreamingContext context)
{
Instance = this;
}
}
Related
I'm having trouble with deserializing a list of objects. For some reason only the first object in the serialized list is returned from the load method. I've looked at numerous questions that seem related, but haven't been able to find a solution to my specific problem. I think it may have something to do with the private backing collection I'm using? Any help would be appreciated. (class names and methods have been made generic)
Here's my deserialization method:
public static ObjectList LoadLibrary()
{
BinaryFormatter formatter = new BinaryFormatter();
FileStream loadStream;
string path = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "ObjectList.bin");
ObjectList lib = null;
if (!File.Exists(path))
{
lib = new ObjectList();
return lib;
}
try
{
using (loadStream = new FileStream(path, FileMode.Open, FileAccess.Read))
{
lib = (ObjectList)formatter.Deserialize(loadStream);
}
}
catch (Exception e)
{
MessageBox.Show("Object list could not be loaded. Error: \n" + e);
}
return lib;
}
Here's my ObjectList class;
[Serializable]
public class ObjectList: IEnumerable<Obj>
{
#region Construction
/// <summary>
/// Contracts Test Case Library Constructor
/// </summary>
public ObjectList() { }
/// <summary>
/// Private backing collection
/// </summary>
private List<Obj> _objectList = new List<Obj>();
#endregion
And for good measure, here's my Obj class:
[Serializable]
public class Obj
{
#region Constructors
public Obj(string Name, string Description)
{
this.Name = Name;
this.Description = Description;
}
public Obj() { }
#endregion
I want do some manipulation on all instances of a CustomType that got created with an XmlSerializer.Deserialize
The best way would be to pass in as a constructor, but "PostSerialization" would work just fine.
In this example, I need to pass in an object to my CustomType based from the XmlSerializer context.
public class CustomType : IXmlSerializable
{
public CustomType()
: this(null)
{
}
public CustomType(Object somethingImportant)
{
}
public void ReadXml(System.Xml.XmlReader reader) { ... }
public void WriteXml(System.Xml.XmlWriter writer) { ... }
}
...
Object somethingImportant = 12345; // I need to pass this to *all* CustomType
var serializer = new XmlSerializer(typeof(MyType));
var reader = new StringReader(str);
return serializer.Deserialize(reader) as MyType;
XmlAttributeOverrides is a good idea, but "MyType" is quite complex, I can't go through all the possible XmlElement to custom create the CustomType.
You could make the Object somethingImportant a thread-static variable, and use it in the constructor when non-null, like so:
public class CustomType
{
[ThreadStatic]
static object deserializationObject;
public static IDisposable SetDeserializationObject(object deserializationObject)
{
return new DeserializationObjectValue(deserializationObject);
}
sealed class DeserializationObjectValue : IDisposable
{
object oldValue;
public DeserializationObjectValue(object value)
{
this.oldValue = deserializationObject;
deserializationObject = value;
}
int disposed = 0;
public void Dispose()
{
// Dispose of unmanaged resources.
if (Interlocked.Exchange(ref disposed, 1) == 0)
{
Dispose(true);
} // Suppress finalization. Since this class actually has no finalizer, this does nothing.
GC.SuppressFinalize(this);
}
void Dispose(bool disposing)
{
if (disposing)
{
// Free any other managed objects here.
deserializationObject = oldValue;
oldValue = null;
}
}
}
private CustomType(object deserializationObject)
{
if (deserializationObject != null)
{
// Handle as needed.
}
}
public CustomType() : this(deserializationObject)
{
}
}
Then set it when deserializing like so:
using (CustomType.SetDeserializationObject("this is a runtime value"))
{
var serializer = new XmlSerializer(typeof(MyType));
var reader = new StringReader(str);
var myType = serializer.Deserialize(reader) as MyType;
}
By publicly setting the deserializationObject only within the disposable wrapper you ensure it's never left around permanently.
In my system I have 16 different classes alike used for statistics. They look like the following
public class myClass : myInheritage
{
private static myClass _instance;
public static myClass Instance
{
get { return _instance ?? (_instance = new myClass(); }
}
public static void Reset()
{
_instance = null;
}
}
They are all made into singletons
myInheritage looks like this:
public class myInheritage
{
int data = 0;
public myInheritage()
{
}
public int Data
{
get { return data; }
set { data+= value; }
}
}
The program is made, so the user chooses which class he wants to make statistics with.
Something like this is what I want
public void statistics(Object myObject, string name)
{
Object x = myObject;
x.Data = 10;
x.Data();
}
Called from another class
statistics(myClass.Instance, "myClass");
statistics(myClass2.Instance, "myClass2)";
So I want to dynamically change my instance in my statistics class.
Is that possible with .NET 2.0 ?
You could use reflection...
MethodInfo method = myObject.GetType().GetMethod("Reset");
if (method != null) method.Invoke(myObject, null);
If you can modify the classes themselves, a better approach might be to have each implement an interface (or base class) IResettable.
public interface IResettable
{
void Reset();
}
public class myClass : myInheritage, IResettable
{
public void Reset() { ... }
}
Then you could write the function against the interface:
public void statistics(IResettable myObject, string name)
{
myObject.Reset();
}
Yes. What you want here is a Strategy/Factory pattern. I name both as they could be used in conjunction for your case. There are great examples of these design patterns here and the following are detailed intros to the Strategy pattern and the Factory pattern. The former of the last two links also shows you how to combine the two to do exactly waht you require.
So in your case, you could set up the following interface
public interface IStatistics
{
// Some method used by all classes to impose statistics.
void ImposeStatistics();
}
Then in you singleton classes you could have
public class myClass : myInheritage, IStatistics
{
private static myClass _instance;
public static myClass Instance
{
get { return _instance ?? (_instance = new myClass()); }
}
public static void Reset()
{
_instance = null;
}
// You would also inherit from IStatistics in your other classes.
public void ImposeStatistics()
{
// Do stuff.
}
}
Then you would have a 'factory' class that imposes you stratgey at runtime.
public static class StatisticFactory
{
public static void ImposeStatistics(IStatistics statsType)
{
statsType.ImposeStatistics();
}
/// <summary>
/// Get the conversion type.
/// </summary>
/// <param name="col">The column to perform the conversion upon.</param>
public static IStatistics GetStatsType(string typeName)
{
switch (typeName)
{
case "BoseEinstein":
return new BoseEinsteinStats();
case "FermiDirac":
return new FermiDiracStats();
default:
return null;
}
}
}
You can then call this like
// Run stats.
IStatistics stats = StatisticFactory(GetStatsType("BoseEinstein"));
to get the statistics for the required class.
I hope this helps.
I have been struggling a bit with some reflection code that I though would be simple. Essentially, I have an interface that defines a method. Then, I have an abstract class that provides a base implementation of that method.
The concrete classes can contain nested instances of other classes that can also derive from the same base class. It can be illustrated by the following sample:
using System.Linq;
public interface ISampleObject
{
bool IsValid();
}
public abstract class SampleObjectBase : ISampleObject
{
public bool IsValid()
{
var returnValue = true;
// Self-validation sets the return value.
var childProperties = this.GetType().GetProperties().Where(pi => typeof(ISampleObject).IsAssignableFrom(pi.PropertyType));
foreach (var childProperty in childProperties)
{
// var childInstance = ????; // Need the actual *existing* instance property, cast to ISampleObject.
// if (childInstance.IsValid() != true)
// {
// returnValue = false;
// }
}
return returnValue;
}
}
public sealed class InnerSampleObject : SampleObjectBase
{
}
public sealed class OuterSampleObject : SampleObjectBase
{
public InnerSampleObject DerivedSampleObject { get; set; }
}
My problem is that in the commented code for SampleObjectBase, I cannot get the concrete instance of the matching PropertyInfo value. If I look at the PropertyInfo object in the loop, I see that the type is correct, but I cannot find a way to directly access the instance that already exists in the implementation. So, when executing, for example, OuterSampleObject.IsValid(), the code finds the PropertyInfo for InnerSampleObject, as expected. I want to execute InnerSampleObject.IsValid().
I have tried (multiple variations of):
var childIsValid = (bool)contractProperty.PropertyType.InvokeMember("IsValid", BindingFlags.InvokeMethod, null, null, null);
And:
var childInstance = (ISampleContract)contractProperty;
The problem with the first one is that I can't pass null in as the target for InvokeMember, as IsValid() is not static (nor can it be, since I am focused on the actual instance). The second on is just a lame cast, but is the gist of what I want to accomplish.
The sample code above is just a minimalist example of what I want to achieve. The full code is part of a self-validating DTO that recursively checks the entire hierarchy and returns what children have validation issues and what they are.
Any help would be greatly appreciated.
How about:
var instance = childProperty.GetValue(this, null) as ISampleObject;
if (instance != null)
{
if (!instance.IsValid())
return false;
}
Please see if the code below is what you are looking for. My changes are marked with a comment starting with //VH:
public interface ISampleObject
{
bool IsValid();
}
public abstract class SampleObjectBase : ISampleObject
{
public virtual bool IsValid()
{
var returnValue = true; //VH: Changed value from false to true
// Self-validation sets the return value.
var childProperties = this.GetType().GetProperties().Where(pi => typeof(ISampleObject).IsAssignableFrom(pi.PropertyType));
foreach (var childProperty in childProperties)
{
//VH: Here is how you get the value of the property
var childInstance = (ISampleObject)childProperty.GetValue(this, null);
if (childInstance.IsValid() != true)
{
returnValue = false;
}
}
return returnValue;
}
}
public sealed class InnerSampleObject : SampleObjectBase
{
}
public sealed class OuterSampleObject : SampleObjectBase
{
//VH: Added this constructor
public OuterSampleObject()
{
DerivedSampleObject = new InnerSampleObject();
}
public InnerSampleObject DerivedSampleObject { get; set; }
}
class Program
{
static void Main(string[] args)
{
OuterSampleObject c = new OuterSampleObject();
c.IsValid();
}
}
Just use
var childInstance = (ISampleObject)childProperty.GetValue(this, null);
I have a List<object> with different types of objects in it like integers, strings, and custom types. All custom types are protobuf-adjusted.
What I wanna do now is to serialize / deserialize this list with protobuf.net. Up until now I suspect that I have to declare each and every type explicitly, which is unfortunately not possible with these mixed-list constructs. Because the binary formater has no problems to do these things I hope that I missed something and that you can help me out.
So my question is how to deal with objects in protobuf.net.
(disclosure: I'm the author of protobuf-net)
BinaryFormatter is a metadata-based serializer; i.e. it sends .NET type information about every object serialized. protobuf-net is a contract-based serializer (the binary equivalent of XmlSerializer / DataContractSerializer, which will also reject this).
There is no current mechanism for transporting arbitrary objects, since the other end will have no way of knowing what you are sending; however, if you have a known set of different object types you want to send, there may be options. There is also work in the pipeline to allow runtime-extensible schemas (rather than just attributes, which are fixed at build) - but this is far from complete.
This isn't ideal, but it works... it should be easier when I've completed the work to support runtime schemas:
using System;
using System.Collections.Generic;
using ProtoBuf;
[ProtoContract]
[ProtoInclude(10, typeof(DataItem<int>))]
[ProtoInclude(11, typeof(DataItem<string>))]
[ProtoInclude(12, typeof(DataItem<DateTime>))]
[ProtoInclude(13, typeof(DataItem<Foo>))]
abstract class DataItem {
public static DataItem<T> Create<T>(T value) {
return new DataItem<T>(value);
}
public object Value {
get { return ValueImpl; }
set { ValueImpl = value; }
}
protected abstract object ValueImpl {get;set;}
protected DataItem() { }
}
[ProtoContract]
sealed class DataItem<T> : DataItem {
public DataItem() { }
public DataItem(T value) { Value = value; }
[ProtoMember(1)]
public new T Value { get; set; }
protected override object ValueImpl {
get { return Value; }
set { Value = (T)value; }
}
}
[ProtoContract]
public class Foo {
[ProtoMember(1)]
public string Bar { get; set; }
public override string ToString() {
return "Foo with Bar=" + Bar;
}
}
static class Program {
static void Main() {
var items = new List<DataItem>();
items.Add(DataItem.Create(12345));
items.Add(DataItem.Create(DateTime.Today));
items.Add(DataItem.Create("abcde"));
items.Add(DataItem.Create(new Foo { Bar = "Marc" }));
items.Add(DataItem.Create(67890));
// serialize and deserialize
var clone = Serializer.DeepClone(items);
foreach (DataItem item in clone) {
Console.WriteLine(item.Value);
}
}
}
List<YourClass> list;
ProtoBuf.Serializer.Deserialize<List<YourClass>>(filestream);
There is a way of doing this, albeit not a very clean way, by using a wrapper object that utilises another serialisation mechanism that supports arbitrary objects. I am presenting an example below using JSON but, like I said, resorting to a different serialisation tool seems like defeating the purpose of using protobuf:
[DataContract]
public class ObjectWrapper
{
[DataMember(Order = 1)]
private readonly string _serialisedContent;
[DataMember(Order = 2)]
private readonly string _serialisedType;
public object Content { get; private set; }
[UsedImplicitly]
private ObjectWrapper() { }
public ObjectWrapper(object content)
{
_serialisedContent = JsonConvert.SerializeObject(content);
_serialisedType = content.GetType().FullName;
Content = content;
}
[ProtoAfterDeserialization]
private void Initialise()
{
var type = Type.GetType(_serialisedType);
Content = type != null
? JsonConvert.DeserializeObject(_serialisedContent, type)
: JsonConvert.DeserializeObject(_serialisedContent);
}
}
EDIT: This can also be done using C#'s built-in binary serialisation
[DataContract]
public class ObjectWrapper
{
[DataMember(Order = 1)]
private readonly string _serialisedContent;
public object Content { get; private set; }
[UsedImplicitly]
private ObjectWrapper() { }
public ObjectWrapper(object content)
{
using (var stream = new MemoryStream())
{
var formatter = new BinaryFormatter();
formatter.Serialize(stream, content);
stream.Flush();
stream.Position = 0;
_serialisedContent = Convert.ToBase64String(stream.ToArray());
}
}
[ProtoAfterDeserialization]
private void Initialise()
{
var data = Convert.FromBase64String(source);
using (var stream = new MemoryStream(data))
{
var formatter = new BinaryFormatter();
stream.Seek(0, SeekOrigin.Begin);
return formatter.Deserialize(stream);
}
}
}