NetMQ / NetMQ.ReactiveExtensions

Effortlessly send messages anywhere on the network using Reactive Extensions (RX). Transport protocol is ZeroMQ.
Mozilla Public License 2.0
66 stars 14 forks source link

Allow other serialisation formats #15

Open drewnoakes opened 8 years ago

drewnoakes commented 8 years ago

For example, I use Dasher which is a MsgPack serialiser for .NET that doesn't require any annotations on your types.

https://github.com/drewnoakes/dasher https://www.nuget.org/packages/Dasher/

sharpe5 commented 8 years ago

Fantastic idea! I like the idea of it just working, that's one of the core aims of the library. I might make this the default.

On Thursday, 11 February 2016, Drew Noakes notifications@github.com wrote:

For example, I use Dasher which is a MsgPack serialiser for .NET that doesn't require any annotations on your types.

https://github.com/drewnoakes/dasher https://www.nuget.org/packages/Dasher/

— Reply to this email directly or view it on GitHub https://github.com/NetMQ/NetMQ.ReactiveExtensions/issues/15.

brisingraerowing commented 8 years ago

I have an idea. How about an interface that defines methods for serializing/deserializing objects and implementations of that interface for different serialization formats (which should be in separate assemblies).

example interface:

public interface ISerializer
{
    byte[] Serialize(object obj);
    object Deserialize(byte[] data);
}

I have used an interface like this myself in some things I have toyed with (usually just playing with different serialization libraries to see which ones I like).

drewnoakes commented 8 years ago

That seems very sensible to me.

Are there any other semantics that need to be captured here? How do we ensure failures are handled in a consistent way? Perhaps TrySerialise/TryDeserialise, or document standard exceptions.

On 4 April 2016 at 02:57, Brisingr Aerowing notifications@github.com wrote:

I have an idea. How about an interface that defines methods for serializing/deserializing objects and implementations of that interface for different serialization formats (which should be in separate assemblies).

example interface:

public interface ISerializer { byte[] Serialize(object obj); object Deserialize(byte[] data); }

— You are receiving this because you authored the thread. Reply to this email directly or view it on GitHub https://github.com/NetMQ/NetMQ.ReactiveExtensions/issues/15#issuecomment-205102446

brisingraerowing commented 8 years ago

Using TrySerialize and TryDeserialize would work, as would documenting standard exceptions. Maybe a custom exception (i.e. SerializationFailureException) would work as well, and have the exception that caused the failure as it's inner exception.

sharpe5 commented 8 years ago

Whenever a program throws an exception, its quite a heavyweight operation. A program can only throw so many exceptions per second before it hits a limit. If we are deserializing at high speed, this really hurts performance.

In addition, every time a program throws an exception that is caught, it pops up in the debugger, if debugging is switched on for the CLR.

For this reason, it is advisable to avoid throwing exceptions except in absolutely dire circumstances, e.g. the program is about to die.

On 5 April 2016 23:01:52 BST, Brisingr Aerowing notifications@github.com wrote:

Using TrySerialize and TryDeserialize would work, as would documenting standard exceptions. Maybe a custom exception (i.e. SerializationFailureException) would work as well, and have the exception that caused the failure as it's inner exception.


You are receiving this because you commented. Reply to this email directly or view it on GitHub: https://github.com/NetMQ/NetMQ.ReactiveExtensions/issues/15#issuecomment-206001967

brisingraerowing commented 8 years ago

OK, true. Then the Try* methods would likely be the best bet. A method to get information on the error that happened would probably be nice, but not required.

brisingraerowing commented 8 years ago

I was thinking about this, and I came up with an idea.

The interface would look like:

public interface ISerializer
{
    bool TrySerialize(object obj, out byte[] result);
    bool TryDeserialize(byte[] data, out object result);
    SomeType GetLastError();
}

The GetLastError() method would return an object that indicates what happened that caused the (de)serialization to fail. I am not sure whether a custom object or a plain old Exception would be best, although using Exception would prevent having to create another class to hold an error state, and allow the caller to decide whether or not to throw the exception.

drewnoakes commented 8 years ago

I think your options are either to use Exception or string to model the error state. Exception models inner exceptions, and in some cases custom properties and so forth. string keeps it simple.

One point, I would suggest not using GetLastError as that's not threadsafe, and makes the implementation stateful. Win32 goes to great deals of trouble to make its GetLastError API work in multithreaded environments. You could maybe use a ThreadLocal, but I'm not sure it's worth it. Plus it makes the user worry whether it's threadsafe or not.

Other options:

Not sure what's best here really. The overhead of exceptions due to receiving junk over a socket could be a problem in high perf cases. Maybe just have the Try form produce an out Exception that's null when the method returns true.

brisingraerowing commented 8 years ago

True. The out Exception would probably be simplest.

Sorry for the late reply. Internet issues (Damn Frontier...) and being very sick don't help.