Comments (8)
Thank you.
Hmn, is this concept match for you?
public interface IDynamicRoot
{
}
[ZeroFormattable]
public class TypeA : IDynamicRoot {}
[ZeroFormattable]
public class TypeB : IDynamicRoot{}
// RegisterDynamic? : key as byte(binary size)
Formatter.RegisterDynamicUnion<IDynamicRoot, byte>(x =>
{
x.Register(key: (byte)0, subType: typeof(TypeA));
x.Register(key: (byte)1, subType: typeof(TypeB));
});
// RegisterDynamic? : key as string(convenient but use many binary spaces)
Formatter.RegisterDynamicUnion<IDynamicRoot, string>(x =>
{
// Scan rules can be freely built(manual? assembly scan +attribute? etc...).
x.Register(key: typeof(TypeA).FullName, subType: typeof(TypeA));
x.Register(key: nameof(TypeB).FullName, subType: typeof(TypeB));
});
// Serialize/Deserialize...
var bin = ZeroFormatterSerializer.Serialize<IDynamicRoot>(new TypeA());
// o is TypeA
var o = ZeroFormatterSerializer.Deserialize<IDynamicRoot>(bin);
If removing the interface root, is this another api suggestion good?(I think this is better)
[ZeroFormattable]
public class TypeA {}
[ZeroFormattable]
public class TypeB {}
Formatter.RegisterDynamicUnion<byte, string>(x =>
{
x.Register(key: (byte)0, subType: typeof(TypeA));
x.Register(key: (byte)1, subType: typeof(TypeB));
return "DynamicUnionName_A"; // key of the dynamic union serializer
});
var bin = ZeroFormatterSerializer.SerializeDynamicUnion("DynamicUnionName_A", new TypeA());
// object(TypeA)
var o = ZeroFormatterSerializer.DeserializeDynamicUnion("DynamicUnionName_A", bin);
from zeroformatter.
Ideally that's what I was thinking about
//consumer types
public class MessageBase {}
public interface IEvent{}
public class UnknownEvent : IEvent {}
[ZeroFormattable]
public class EventA : IEvent {}
[ZeroFormattable]
public class EventB : IEvent {}
public class UnknownMessage : MessageBase {}
[ZeroFormattable]
public class MessageA : MessageBase {}
[ZeroFormattable]
public class MessageB : MessageBase
{
[Index(0)]
public virtual List<IEvent> Events { get; set; }
}
[ZeroFormattable]
public class MessageBatch : MessageBase
{
[Index(0)]
public virtual List<MessageBase> Messages { get; set; }
}
//serialiser registration
var serialisationModel = ZeroFormatterSerializer.CreateDefaultModel()
serialisationModel.RegisterTypesWithAttributes(someAssembly);
serialisationModel.RegisterPolymorphicType<IEvent, int, UnknownEvent>(x =>
{
//can be easily extended to reflection based scan if library consumer wants it
x.Register(key: SomeIdGen(nameof(EventA)), subType: typeof(EventA));
x.Register(key: SomeIdGen(nameof(EventB)), subType: typeof(EventB));
});
serialisationModel.RegisterPolymorphicType<MessageBase, int, UnknownMessage>(x =>
{
x.Register(key: SomeIdGen(nameof(MessageA)), subType: typeof(MessageA));
x.Register(key: SomeIdGen(nameof(MessageB)), subType: typeof(MessageB));
x.Register(key: SomeIdGen(nameof(MessageBatch)), subType: typeof(MessageBatch));
});
MessageBase msg = new MessageBatch { Messages = new List<MessageBase> { new MessageB { Events = new List<IEvent> { new EventA() }}};
var serialiser = ZeroFormatterSerializer.CreateFromModel(serialisationModel);
var bts = serialiser.Serialise(msg);
var message = serialiser.Deserialise<MessageBase>(bts)
ZeroFormatterProtocolGenerator.CompileFromModel(serialisationModel, "path\UnityCompatibleProtocol.dll");
The reason for UnknownMessage/UnknownEvent is backward compatibility, so that when you read List in older client instead of failing on deserialisation it can just fallback to set them as UnknownMessage allowing layer above to skip new unknown messages without losing known ones.
The reason for non-static serialiser class is so you can have differently configured serialisers in same AppDomain. It's generally better to have non-static implementation that is exposed in preconfigured static wrapper class, because you can always create a user friendly singleton from non-static class but not other way around.
Also because protocol is generated at runtime we need to be able to generate precompiled dll for unity from it, so in addition to command line tool I suggest exposing protocol generator as part of library
I really like the library btw, if it wasn't for the protocol like above I would have already switched from Protobuf-Net to ZeroFormatter
from zeroformatter.
Thank you, I understood.
Based on your suggestion, I thought about a new API.
public interface ITypeResolver
{
// can be precompiled for improve initial performance(or AOT environment).
// precompiled generator always set to false.
bool IsUseDefaultDynamicSerializer { get; }
// AppendFormatterResolver in normal.
object ResolveFormatter(Type type);
// RegisterPolymorphicType
object ResolveDynamicUnion(Type unionType, DynamicUnionResolver resolver);
}
public class CustomSerializationModel : ITypeResolver
{
public bool IsUseDefaultDynamicSerializer
{
get
{
return true;
}
}
public object ResolveFormatter(Type t)
{
return null;
}
public void ResolveDynamicUnion(Type unionType, DynamicUnionResolver resolver)
{
if (unionType == typeof(IEvent))
{
// resolver api is [Type, object] for reflection based regsiter(but not typesafe)
resolver.RegisterDiscriminatedKeyType(typeof(int));
resolver.RegisterFallbackType(typeof(UnknownEvent));
resolver.RegisterSubType(key: SomeIdGen(nameof(EventA)), subType: typeof(EventA));
}
// else if...
}
}
// chnage Formatter<T> to here
public abstract class Formatter<TTypeResolver, T>
where TTypeResolver : ITypeResolver, new()
// usage
// mark DynamicUnion on base type...
[DynamicUnion]
public class MessageBase {}
[DynamicUnion]
public interface IEvent{}
/// use dynamic serializer
ZeroFormatterSerializer.CustomSerializer<CustomSerializationModel>.Serialize();
// create dll
// ZeroFormatterProtocolGenerator.CompileDefault();
// ZeroFormatterProtocolGenerator.Compile<CustomSerializationModel>(IEnumerable<Type> generateTypes,string typeFullName, string path);
// ZeroFormatterProtocolGenerator.Compile<CustomSerializationModel>(IEnumerable<Assembly> scanAssemblies,string typeFullName, string path);
// use dll
// ZeroFormatterSerializer.SetDefault<GeneratedSerializationModel>();
// ZeroFormatterSerializer.Serialize();
Serializer acquisition by static type is the core of ZeroFormatter and can not be changed.
However, it can be solved by static type with custom type.
I hope these changes will satisfy your requirements, and I want you to switch:)
from zeroformatter.
That looks good.
My only question is around performance with CustomSerializationModel
... to make it fast reflection based scan should happen only once and mapping of type->formatter should be cached otherwise ZeroFormatterSerializer.CustomSerializer<CustomSerializationModel>().Serialize();
will be prohibitively expensive.
Or is you plan that consumer just saves instance of serialiser :
//once on startup
var serialiser = ZeroFormatterSerializer.CustomSerializer<CustomSerializationModel>();
//many times, threadsafe
serialiser.Serialise();
Cheers
from zeroformatter.
ZeroFormatterSerializer.CustomSerializer<CustomSerializationModel>.Serialize<T>(T value)
calls
Formatter<CustomSerializationModel, T>.Default.Serialize(T value)
;
so
Formatter<CustomSerializationModel, T>.Default
is automatically cached on static field.
from zeroformatter.
Understood, but how the caching for void ResolveDynamicUnion(Type unionType, DynamicUnionResolver resolver)
will be working? As read through cache on first time you serialise something that contains IEvent(for example)?
from zeroformatter.
Yes, that cache will be done for the first time.
This is the flow at the time of caching.
CustomSerializer<CustomSerializationModel>.Serialize<IEvent>()
->
Formatter<CustomSerializationModel, IEvent>.Default
->
ResolveDynamicUnion(typoef(IEvent), resolver)
->
Formatter<CustomSerializationModel, IEvent>.Default = resolver.CreateFormatter()
// cached!
from zeroformatter.
Today I released 1.5.0
and it supports DynamicUnion
.
Currently supports ITypeResolver configuraiton
, RegisterDynamic
, Fallback type on Union
.
DLL code generate is not yet.
from zeroformatter.
Related Issues (20)
- Error: Bad IL format. Please support .NET Core 3.0, 3.1 HOT 13
- Serialization issues with large dictionary HOT 2
- What is the outpur format of this serialzier? HOT 2
- Null reference exception in zero formatter
- Support array of Objects
- Reserializing object throws ArgumentException
- Analyser crash (ZeroFormatterCodeFixProvider)
- Ignore formats removes next node
- Attribute decorate existing classes at runtime / Run with no decoration.
- Serializing List of Byte array() HOT 1
- Image serialize to and from bits per pixel formats? HOT 2
- Can this deserialize directly into a existing object?
- Why is [index] and virtual required?
- Why is Structure of Type SizeF not supported ?
- Bad IL Format. HOT 1
- Is ZeroFomatter can be used now on other platforms, than Windows, on the development machine?
- System.InvalidOperationException: Type is not supported
- Can't reload saved data
- Analyzer does not check for access modifiers on parameterless constructors
- Problem with C# .NET 6
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from zeroformatter.