To make a long story short I am currently writing an RPG using WPF and C#. I recently decided to implement(or try to at least) Protobuf-Net as the BinaryFormatter class just does not give the performance as Protobuf.
Basically, due to a severe lack of documentation I have been trying to put bits and pieces together that google has shown me. My current problem is that I cannot get any inherited classes to serialize using a generic function. I require this as the bulk of my work is an API so any new types that are created can be serialized.
An example of what I require,
public sealed class SomeClass
{
private RuntimeTypeModel protobuf = RuntimeTypeModel.Create();
public T DeepCopy<T>(T template) where T : IsSomeBaseClass
{
Type templateType = template.GetType();
this.protobuf.Add(templateType, true);
// Get inherited classes.
//
//
return (T)this.protobuf.DeepClone(template);
}
}
Is this even possible with Protobuf-Net? If someone could give me a push in the right direction that would be much appreciated.
Related
Background Info
I have a .Net Standard 2.0 class library that uses Protobuf-net.grpc's code first approach to define a gRPC service. In this definition I have classes defining different data structures that we are using to record sensor data and serialize this out using protobuf-net. My programs are ingesting serveral hundred thousand large objects /s (which will soon scale into the millions) and are intended to be used in embedded environments.
Problem
In my class below, I would like to include as a member a System.Numerics.Quaterion. I cannot seem to get this serialized out. Using static constructors, the RuntimeTypeModel throws exceptions as the Quaternion model has somehow already been created by the time the static constructor is executed. As this is a class library, and I desperately want to avoid invoking the RuntimeTypeModel in each different program using the gRPC service. I'm hoping to find a way to serialize the System.Numerics.Quaternion.
I have tried placing this static constructor runtime definition at the highest level of the class hierarchy to no avail. Exceptions still thrown.
[ProtoContract]
public class IMUData : SensorData, ISensorData
{
static IMUData()
{
RuntimeTypeModel.Default.Add(typeof(Quaternion), false)
.Add("W")
.Add("X")
.Add("Y")
.Add("Z");
}
... //Other members
[ProtoMember(8)]
public Quaternion Orientation
{
get; set;
}
... //Other methods and members
}
Question
Is what I would like to do even possible, or should I simply create my own Quaternion class and define implicit operators? (I'd rather avoid this as processing billions of these objects takes long enough)
This is ultimately a timing problem - when the serializer attempts to reflect on SensorData to prepare the serializer, the static constructor in IMUData has not yet executed, so it prepares the serializer with incomplete information, and then later the static constructor tries to reconfigure the model - too late.
If you use C# 9.0, you can fix this by using a module initializer instead of a static constructor (if we assume that SensorData and IMUData are in the same module, which is probably a safe assumption). The following works fine, for example:
[ProtoContract]
public class IMUData : SensorData //, ISensorData
{
[ModuleInitializer]
internal static void Init()
{
RuntimeTypeModel.Default.Add(typeof(Quaternion), false)
.Add("W")
.Add("X")
.Add("Y")
.Add("Z");
}
Note that if you're not using .NET 5 (preview, currently), you can define the necessary attribute yourself:
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
internal sealed class ModuleInitializerAttribute : Attribute { }
}
If this isn't an option, you can simply put the model configuration code much earlier in your application - ideally during startup, so that it happens long before the serializer attempts to start building models.
I am using Unity3D to create an RPG game similar to Final Fantasy and such. In c# of course.
For entities in the game, there are two separate classes: Character and Enemy.
For my battle code, I have two lists, one List called Party, and one List called Enemies.
I often need to compare and modify int values of ALL Characters and Enemies together, which was difficult to do because they are in separate lists. They have the same variables with the same names, e.g. (int Reflex, int Attack, int Strength, int Defense, etc. ) but they are a different type, so I don't know to do, for example, get the Character OR Enemy with the highest Reflex out of both lists for example.
My immediate inclination was to use them as derived classes, have both Character and Enemy inherit from a base class Entity with their overlapping variables contained in that. Then I could have one list of Entity in the battle to use. SO much easier, BUT damn Unity3D does not support polymorphism for its serialization process which all of my saving and loadings currently depends on.
I am hoping there is an easier answer for this; otherwise, I will have to painfully rewrite all of my saving and loading code, somehow, to not use Unity's serialization...
So basically, can I compare these variables things easily? And if so, how?
EDIT: Answered my own question
This might be kind of ridiculous so soon after having asked the question, but I just unexpectedly came across a very nice blog post describing the same problems that I was having:
http://www.archmagerises.com/news/2015/9/22/tips-on-game-world-state-data-serialization-in-unity-c
Following his example, I implemented sharpSerializer in my game. It works great, and I returned to my initially planned system of polymorphic classes.
Now I don't have to try to force my code to work around Unity's awful built-in serializer.
I wanted to post this because there don't seem to be many posts either on the Unity forums or here which address this issue, so anyone has the same problems as me can find a nice fix.
Unity's built-in serializer could use a lot of work, but I've really only run into real-huge headaches while doing editor scripting. Like, I very much sympathize with this guy's rage. Run-time serialization is a bit different, it's a bit easier to work with, especially with the help of an external tool like JsonDotNet for Unity, or I see you've mentioned elsewhere SharpSerializer. There's also FullSerializer and it's asset store offshoot FullInspector, which is intended specifically to help deal with those uniquely frustrating editor scripting headaches.
A couple things to note: Unity does support polymorphism for UnityEngine.Object derived classes, and this of course includes MonoBehaviour. As for custom classes, you can implement the ISerializationCallbackReciever interface if these classes have properties (such as Dictionary) which unity cannot by default serialize. Otherwise you just add the [Serializeable] tag to the class to let unity know that you want that data to be saved. There are a few other caveats you should familiarize yourself with, see : https://blogs.unity3d.com/2014/06/24/serialization-in-unity/
Using your use case as an example, the usual structure might look something like this:
[Serializeable]
public Class ActorProperties{
public int CurrentHealth;
public int MaxHealth;
public int Range;
}
public Class Actor : MonoBehaviour{
[SerializeField] protected ActorProperties _actorProperties
public ActorProperties ActorProperties{
get{ return _actorProperties;}
set{_actorProperties = value;}
}
}
public Class Character : Actor{
// Character specific code
}
public Class Enemy : Actor{
// Enemy specific Code
}
public Class GameManager : MonoBehaviour{
private List<Actor> enemies;
private List<Actor> characters;
public List<Actor> AllActors{
get{
List<Actor> returnList = new List<Actor>(characters);
returnList.AddRange(enemies);
return returnList;
}
}
public Actor GetActorWithHealth(float healthCheck){
Actor actor = AllActors.Find(x => x.ActorProperties.CurrentHealth == healthCheck);
return actor;
}
}
Aside from Non-Serialized DataTypes, the example below illustrates most common instances when custom serialization is needed.
// Even though Properties is marked as Serializeable, it's 'data' property
// won't get serialized if we're serializing a reference to an ActorProperties.
// No native support for polymorphic serialization of custom classes.
[Serializable]
public class Properties{
public float data;
}
[Serializeable]
public class ActorProperties : Properties{
// Here we have a recursion problem because Unity cannot serialize
// null values for custom classes. Unity will try to serialize this ActorProperties field, which in turn starts the serialization over again,
// with an iteration depth of 7. Killer if it were a List<ActorProperties> .
public ActorProperties EnemyProperties;
public int CurrentHealth;
public int MaxHealth;
public int Range;
// Since Unity treats custom classes like structs, the following field wont be serialized
// as a pointer to an existing object, but as a unique instance of it's class.
public CustomClass SharedReference;
}
Serialization solutions like Json.NET for Unity et. al. go a long way towards making the serialization process easier, but regardless of what solution you use, it's extremely important to pay attention to precisely how your data is going to be serialized.
Personally I would recommend Json.Net for Unity, but the only other assets I've had some experience with is FullSerializer and FullInspector. I've not used SharpSerializer.
Why not abstract away the data for Characters and Enemies by using a Plain Old C# class with an ID field? (maybe called something like "CreatureData" "ActorData" or "CharacterData"). Each instance of this abstract class could then reference this new ID field that is contained within both Characters and Enemies.
Instances of the new C# class could then be stored in another collection of some kind like a dictionary or a list and easily iterated through later.
Unless I'm mistaken, as long as you make this new class serialize-able, Unity should still be able to handle it.
Give an object similar to:
public class MyObject : IInterfaceA
{
public IEnumerable<IInterfaceB> MyList{get; set}
public MyComplexObjectX{get; set;}
public MyComplexObjectY{get; set;}
}
which may have a fairly complex graph.
Does anybody know the best means of serializing this whereby namespace changes would not be an issue on deserialization? Would Json be the way to go perhaps?
Secondly there is also a good bit of use of lists of interfaces, generics etc. Im happy to use known types with DataContractSerializer but I think I will have the issue with namespace changes then.
Performance, size of serialized object etc are not an issue for me right now.
Thanks.
I have recently tried to play around with MongoDb's serialization. Basically, I am trying to use the driver's serializer to store my models while at the same time attempting to avoid any dependencies between my well-known model classes and 10gen's MongoDb C# driver (v1.2, if it matters).
This, by itself, is no issue. What is problematic however is that there can be (dynamic) information stored for some of the objects side by side to well-known elements. I could do this by using the [BsonExtraElements] attribute, but as I said above, I am trying to avoid coupling my models to MongoDb. Model classes that can have this behaviour, implement a certain interface:
public interface IHaveMoreInformation
{
IDictionary<string, object> Extra { get; set; }
}
For this, I have tried to write a custom convention that gets registered in the convention profile at application startup:
public sealed class ExtraElementsConvention : IExtraElementsMemberConvention
{
#region Implementation of IExtraElementsMemberConvention
public string FindExtraElementsMember(Type type)
{
return typeof(IHaveMoreInformation).IsAssignableFrom(type) ? "Extra" : null;
}
#endregion
}
This is where the problem starts. The driver expects a BsonDocument property (again, I don't want to couple). I was hoping there is a way to work around this and serialize this additional information into an IDictionary<string,object> instance.
I am helpful for any ideas to achieve this.
Thanks in advance,
Manny
After looking into the driver's inner workings, I've decided to take the matter to mongoDB's issue tracking system. Until now (1.3.1), the driver seems very keen on only accepting a BsonDocument property for extra elements; this would effectively couple models to types declared by the driver, which is a bit of a pain when you decide to switch technologies.
The issue is currently being tracked here:
https://jira.mongodb.org/browse/CSHARP-395
Hopefully this improvement will find its way into 1.4 and help people looking to achieve something similar in the future.
I've been using SubSonic 2 for a while now, but as I am starting a new project, I'd like to upgrade to 3. In my old project, I used a custom, non-sustainable hack to serialize things for web services. I really would like to find a more elegant solution.
I'm using Mono, so I need to stay within implemented classes, e.g. DataContractSerializer is probably out. Still on ASMX, though would love to upgrade to WCF as soon as the support is solid. Moonlight/Silverlight will be the initial clients. JSON/protobuf in the future...
The standard Xml serializer is opt-out, so I'd need some way to take control of it. Which brings me to IXmlSerializable. I'm rather unfamiliar with SS's templates, but it seems that editing these would allow me to generate the serialization code necessary to not touch the rest of the hierarchy chain. Is this a "good idea"?
I'd love to just use SS's POCO support, but I don't think it supports complex types or arrays.
Other thoughts/options?
IXmlSerializable is IMO more than a little awkward to get right. Note that if you are handling the XmlSerializer code yourself you can override everything at runtime by using the constructor that accepts XmlAttributeOverrides (but if you use this you should cache and re-use the XmlSerializer instance, or it will leak like a sieve).
You briefly mention protobuf; note that protobuf-net (even in v1) allows you to add member-level serialization data at the type level, so you can include that information in a partial class alongside a generated type:
// file 1
partial class GeneratedClass
{
public int Foo { get; set; }
public string Bar { get; set; }
}
// file 2
[ProtoPartialMember(1, "Foo")]
[ProtoPartialIgnore("Bar")]
partial class GeneratedClass {}