Given a .proto that looks like this:
message Base {
string Dummy = 1
}
message Derived {
Base Super = 1
string Parp = 2
}
... And some C# something like:
public class Base {
public string Dummy;
}
public class Derived : Base {
public string Parp
}
How would one go about customising the serialisation in protobuf-net to be able to do this? Initially I started looking at using a TypeModel and calling AddSubType for the Base MetaType, but then it seems it creates type definitions for Base with optional fields of all the derived classes (ie the other way around vs what I require)
I thought I might be able to walk the hierarchy myself but looking at TypeModel, it seems to support supplying the type to Deserialise but it uses value.GetType() during serialisation. Even then it wasn't entirely clear how I might do this. Is my only option to use ProtoWriter to write every field by hand? This is what I am currently attempting, but I hoped there was an easier way.
The first thing to note is that protobuf itself does not support inheritance. There is no "official" layout for this. Protobuf-net will not support serialization the way you desire: the choice of sub-type encapsulation (rather than base-type encapsulation) was made to fix several issues, including:
satisfying the Liskov substitution principle
working correctly when the serialized type was not known/expected by the caller
basically, working at all (for anything other than the simplest example where both ends know in advance exactly which sub-type they are getting, which largely defeats the point of polymorphism)
However, you could map the DTO manually, basically so your DTO layer doesn't use inheritance at all.
Related
Suppose I have a such class:
public class Class1 {
public int x1;
public Class2 x2;
public double x3;
}
public class Class2 {
public int y1;
private int x2;
}
It there any way to get all the type information of all serializable members (I think its all public fields and properties without explicit statement to a private member) of Class1?
For example, I want to create such a type tree:
<Class1>
<x1>int</x1>
<x2>Class2</x2>
<Class2>
<y1>int</y1>
</Class2>
<x3>double</x3>
</Class1>
The tree will expand unless this member is an atomic type (like int, double, List and all system defined type).
My idea
I know I can use reflection and deep first search to do this thing. But I found out things may become complex because the class can be a generic class. And I'm concerned whether there is more complex situation than generic class.
So there is any better solution than using reflection and deep first search to create this tree?
There is no out-of-the-box way to do this, and there is'nt too many boundary there is only generics, there are easy ways to get the generic type parameters and you will have to recurse them.
However i think you are trying to solve this the wrong way.
If i understand you correctly, you want to protect against serialization issues. I would come at this from a different angle.
Decorate you classes with interfaces to insure a contract.
And/order put your classes/interfaces in a Class Library where they are less likely to be bumper, or even take a step further and nuget them.
If you are truly worried about serialization issues, use a contract based serializer like DataContracts, that breaks if changed and can be versioned.
Update
users owns the classes which need to be serialized.
I used XmlSerializer to serialize and deserialize it.
The problem I want to solve is:
First, user defined the Class1 like above, and it's
deployed to both machine A and machine B.
Then users added a public
field x into Class1, the deployment of machine A is quicker than B. so
machine A recongnized the newly added x. But machine B's deployment is
slower, so machine B don't know x, then the serialization will broke
for machine B.
So now I want to make sure no more changes of the
classes passed to my serializer.
Then you need reflection, there is no library i can think of that does what you want. You will have to dig into generic types and recuse, end of story
I believe that FormatterServices.GetSerializableMembers will return all serializable members, as you originally asked in your question.
This question already has answers here:
How do I use reflection to call a generic method?
(8 answers)
Closed 4 years ago.
I defined various classes like this:
public class Subclass<T> : BaseObject<T>, IObject, IObject<T> { ... }
BaseObject<T> contains all the functionality I need. IObject<T> allows it to be accessed between projects. IObject allows collections to be created: List<IObject>.
BaseObject<T> and IObject<T> have a property T Value;
So I have
public class BaseObject<T> // T is double, int, decimal, long, short, int - in fact anything enumerable
: IObject, IObject<T>
{
[...]
T Value;
[...]
}
The problem I am trying to solve is how to unpack this by type T.
I want to write this function but don't know how in C#:
public void DoProcessing(List<IObject> objectsToBeProcessed)
{
foreach(dynamic singleObject in objectsToBeProcessed)
{
Type unpackedType = [somehow retrieve the type]
BaseObject<unpackedType.GetType()> unpackedObject = [do some kind of conversion of singleObject];
ProcessorClass<unpackedType.GetType()> processor = new ProcessorClass<unpackedType.GetType()>();
processor.Process(unpackedObject);
}
}
I'm finding this quite hard to put into words but I hope that this explanation gets the idea across. Basically I lose the type information when I build the List<IObject> and I need it back later on when I pass it across into another assembly. I want a single central DoProcessing method that can then delegate by type to instances of generics.
How can I get the type information back?
I understand that generics need a type known at compile-time. But this is situation where you only know the type at runtime. The dynamic keyword allows the collection to be iterated, but I haven't found a way to create the bit inside the loop.
Or should I just force everything to a double in BaseObject and then cast it back locally in some way?
I'm a bit lost on this and feel I am missing something obvious. Any ideas welcome.
POSTSCRIPT - CLARIFICATION
The purpose of this is to separate the code-base into two assemblies:
The assembly with BaseObject<T> allows customers and third parties
to write their own business logic which we don't need to see. They
simply subclass the BaseObject into their own code.
The assembly with IObject & IObject<T> contains generic business
logic that we are creating.
We need this separation in so customers can develop their own libraries of code without having to submit it to us. They just send us a list of List<IObject> and we do the rest, calling their subclasses back as necessary.
Surely it is possible!
ALTERNATIVELY
Can anyone suggest a better architectural solution to the two assembly solution I have described i.e. concrete classes in customer code assembly & abstract/interfaces in our framework assembly.
SOLUTION
OK so I've found a simpler solution. Late-binding via Reflection is doable but is hard to implement with my nuanced object model.
Instead, I have replaced the generic type T and implemented a property which is an enum of
public enum ValueType
{
Double,
Boolean,
Integer,
...
}
I then implement overloaded constructors, added this property to the non-generic interface IObject and have removed the generic interface IObject<T> as it's no longer needed.
Returning the value as double or bool is then handled by
public double AsDouble();
public bool AsBoolean();
public int AsInt();
...
in the interface.
It's not elegant or theoretically pure but it means I don't lose type information and can treat instances all the same. I just unpack the ValueType and choose different behaviour programmatically. It also avoids using the dynamic keyword as all values are implemented as double so looping is easy to implement.
On the plus side I have removed a lot of constraints on generics as they were needed up the inheritance hierarchy. It was getting really complicated and the compilation errors were getting too difficult to unravel.
It feels a bit unsatisfactory from a purist perspective, but MongoDB does something similar so that's good enough for me.
I do feel however that C# is "unfinished" in this area and needs a way to upcast or downcast more easily. It's just such an obvious thing to add.
Maybe the Reflection can be wrapped up somehow to make it transparent to the programmer.
Over-engineering, pragmatism and purism. These are the things that weigh on me...
This should be enough to return the type of the object inside your loop:
Type unpackedType = singleObject.GetType();
Note: I know this is an awful idea in practice; I'm just curious about what the CLR allow you to do, with the goal of creating some sort of 'modify a class after creating it' preprocessor.
Suppose I have the following class, which was defined in another assembly so I can't change it.
class Person {
public string Greet() => "Hello!";
}
I now define an interface, and a method, like the following:
interface IGreetable {
string Greet();
}
// ...
void PrintGreeting(IGreetable g) => Console.WriteLine(g.Greet());
The class Person does not explicity implement IGreetable, but it could do without any modification to its methods.
With that, is there any way whatsoever, using Reflection, the DLR or anything else, in which an instance of Person could be passed successfully to PrintGreeting without modifying any of the code above?
Try to use the library Impromptu-Interface
[The Impromptu-Interface] framework to allow you to wrap any object (static or dynamic) with a static interface even though it didn't inherit from it. It does this by emitting cached dynamic binding code inside a proxy.
This allows you to do something like this:
var person = new Person();
var greeter = person.ActLike<IGreetable>();
You could use a dynamic wrapper object to wire this up yourself, but you lose type safety inside the wrapping class:
class GreetableWrapper : IGreetable
{
private dynamic _wrapped;
public GreetableWrapper(dynamic wrapped)
{
_wrapped = wrapped;
}
public string Greet()
{
return _wrapped.Greet();
}
}
static void PrintGreeting(IGreetable g) => Console.WriteLine(g.Greet());
static void Main(string[] args)
{
PrintGreeting(new GreetableWrapper(new Person()));
Console.ReadLine();
}
This may be quite easy soon. Type classes may be introduced to C# as shapes where you will be able to define features of a class and code against that shape and then make use of your code with any type that matches without the author of that code having to declare anything, pretty much as you describe.
The closest thing in C# right now is perhaps how foreach works with a type that has an GetEnumerator() returning an object of a type with a MoveNext() and Current even they don't implement IEnumerable etc. only while that is a built-in concept the compiler deals with, here you could define them.
Interestingly, it will also let you define static members.
I don't believe this is possible. The compiler needs to see something that explicitly implements the interface or class so that the compiler can confirm everything is implemented.
If you could do it using redirection, you could fail to implement something. And that goes against the safety approach embraced by .NET.
An option is creating a wrapper class over the person and pass this wrapper to the method, the wrapper need to explicitly implement the interface.
If you have control of the external code, and are willing to wrap the object (and it seems like all of the answers here wrap), dynamic binding and libraries like Impromptu-Interface seem to me like a lot of trouble for something that's essentially a one liner.
class GreetablePerson : Person, IGreetable { }
And you're done.
When the compiler is building up the GreetablePerson class, the method from Person ends up doing an implicit implementation of the interface, and everything "just works." The only irritation is that the code outside has to instantiate GreetablePerson objects, but in standard object oriented terminology, an instance of GreetablePerson is an instance of Person, so this seems to me like a valid answer to the question as asked.
If the requirements are changed such that you also have pre-existing instances of Person, then something like Impromptu-Interface may become more tempting, but even then you may want to consider giving GreetablePerson a constructor that copies from Person. Choosing the best path forward from there requires getting more details about the requirements and the actual implementation details of the Person class in question.
In sort of an unrelated not, this is something that is commonly done in other languages, such as Scala and Haskell.
It's known as using what are called "type classes". Type classes essentially allow you to define behavior for a type as if it explicitly implemented an interface, without actually requiring it to do so. You can read more about it here.
Going on with my quest to bend protobuf-net to my own will..
I've seen a few questions around SO on how to add sub-classes dynamically
for the serializer to be able to encode the sub-class.., like this or this
My situation is bit different, I have a base class that might get sub-classed in late-bounded code, and I want to serialize is as the BASE class, and completely ignore the sub-class's fields/properties.
The reason I need this, is that later on, when I deserialize the data, the sub-class's code will not be even available, so constructing the sub-class will not be even possible.
Is there a way to limit/prohibit sub-class serializtion?
In my case I have a List where some items in the list are DerivedClass.
I would like to find a way to make protobuf-net serialize everything as BaseClass and to deserialize to BaseClass as well...
I've tried peering into code, but haven't found something too useful.
Normally, the library is very particular about spotting derived classes - and treating them differently from the base class. The only current exception to that is proxy classes, in particular Entity Framework and NHibernate. For a tidy solution, it would seem practical to add some kind of "ignore subclasses" switch. But while that doesn't exist, a very lazy (and hacky) approach would be to cheat using the existing handling for NHibernate, for example:
namespace NHibernate.Proxy {
interface INHibernateProxy {}
}
...
public class SomeDerivedType : BaseType, INHibernateProxy {}
this will then automatically be serialized as per BaseType. It does have a faint whiff of cheating about it, though.
A couple of friends was discussing the use of inheritance and how to check if a subclass is of a specific type and we decided to post it here on Stack. The debate was about if you should implement a abstract enum in the base class to be used for checking the type of the subclass, or if you should use the is operator.
Alt 1.
public abstract class Document{
}
public class PDF:Document{
}
Check: If (myobj is PDF)
Alt 2.
public abstract class Document{
public abstract DucumentType TypeOfDocument {get;}
}
public class PDF:Document{
public DucumentType TypeOfDocument { get{return DucumentType.PDF };}
}
public enum DucumentType{
PDF, Word
}
Check: If (myobj.TypeOfDocument == DucumentType.PDF)
The ones for Alt1. ment that Alt2 slightly breaks SRP, you don’t take advantage of OO, Your repeating the abstraction. Since inheritance is the hardest connection between classes you cannot avoid knowing of them, and if you must go thru with inheritance minimize the impact. Alt2 also breaks DRY
The ones for Alt2 ment that Alt2 will be removing type checking entirely and replacing it with the option of checking this enum instead. Removing all hard connections to all subclasses, and the value of the enum itself does not say anything about which concrete implementation thats currently beeing operated on.
Whats your opinion about the two alternatives?
No discussion of inheritance vs. composition etcetera, that’s another question!
Why do you need to know in the first place? I agree that it's occasionally necessary, but where possible you should make the Document type have appropriate abstract functionality to allow the specialization to be done through inheritance rather than the caller having to treat it differently.
I would only use the enum approach if different subclasses may share document types but withotu wanting to share an inheritance hierarchy. This would be pretty rare, IME.
IMO you should use the is operator.
It gives you the same result without tainting the (abstract) class code.
I've got a similar situation, except that in my case, the DocumentType enum needs to grow as various types are added. By using the Enum, type checking is much better, but it requires that the "generic" base class be recompiled every time a new DocumentType is added.
The alternative I'm currently pondering is to use an interface property to return the type as a STRING. It's not great for type checking, but the rest of my code has the necessary validation to prevent rogue DocumentType objects. I would prefer a different solution, but nothing comes to mind.