Inheritance and known type issue - c#

I'm trying to use protobuf .net to serialize an instance of a class which is inherited from a base class. When trying to serialize\deserialize i'm getting an exception about "type not expected". As I already read, adding the protoinclude with the derived type to the base wil solve the problem. BUT, my problem is that I can't add the attribute, since I don't know the types that will derive my base. As I already read, I understand that V2 is going to provide a way to define a type model in order to describe inheritance. So my questions are:
When V2 release will be avilable?
Is there a workaround in the mean time to solve this issue?
Thanks in advance,
Gil

V2 is available both from nuget and google-code (nuget is a few revs ahead IIRC - and both are a little behind the head). There are a few v1 features not yet re-implemented, but for most purposes you won't notice this. They will be re-added in due course.
Re your problem; that is available via MetaType.AddSubType - however, to use that approach you must be able to reproduce the same int identifiers per-subtype in the future - they are important keys and must not change.
RuntimeTypeModel.Default[typeof(SomeType)].AddSubType(7, subType);
There is also DynamicType available on "object" properties - however this has a few kinks with inheritance-based models; I would avoid that for now (this too will be rectified shortly).

Related

Which strategy can be used when converting back and forth between a domain class and several versions of the same target class?

For my specific context I control the target classes. They were auto-generated based on XSDs and have huge overlaps because they represent different versions of the same class.
Each version is a huge C# class of over 5.000 lines.
Support can't be dropped for old versions. This means we always need to be able to map the domain class to several different versions and back again. There are always small but breaking changes from version to version. More than 90% of the target class is always the same, even if the code is duplicated for each version.
Currently there is one big mapping for each format, which is a horror. There is so. much. duplicated. code. Furthermore, developers tend to make updates where they need it, and skip everything else, which means individual versions often go out of sync, meaning that one version will be updated to do something that other versions don't. This is also not ideal.
So my question to you is: What strategy can you use for this kind of mapping?
Given the size of your classes, and having to maintain multiple versions, I'd suggest serializing and serializing. Assuming that they otherwise approximate one another, JsonConvert doing JsonConvert.Deserialize<TargetClass>(JsonConvert.Serialize(sourceClass)) should solve it, though I've not worked with such large models to have any idea on how performant it is.
Alternatively, you could use a t4 template (if you're not in .net Core anyway) to generate the mapping using reflection into a common method or whatever.
As far as preventing the Developer problem... Interfaces, base classes that define as much of this centrally as possible. Code reviews to ensure that developers are making changes to the lowest layer they possibly can.
You can do some tricky things with inheretence with static using statements, I'm pretty sure.
Something dumb like
using OldVersion = path.to.the.class.CantRenameThis;
class CantRenameThis : OldVersion
We ended up with a solution that achieved the main targets:
Decent compile-time safety to spot mapping errors
De-duplication of code
No messing with the auto-generated code
We did this by exploiting that the auto-generated classes are generated as partial. That means we can extend them.
We ended up creating hierarchies of interfaces/classes looking like this:
ClassV1 implements IClassVerySpecificV1
ClassV2 implements IClassVerySpecificV2
IClassVerySpecificV1 implements SpecificA, SpecificB, SpecificC and IClassBasic
IClassVerySpecificV1 implements SpecificB, SpecificC, SpecificD and IClassBasic
A mapper would then look like:
ClassV1Mapper requires a SpecificAMapper, SpecificBMapper, SpecificCMapper and ClassBasicMapper
ClassV2Mapper requires a SpecificBMapper, SpecificCMapper, SpecificDMapper and ClassBasicMapper
This way we could map 90% of everything by just throwing everything that belongs to IClassBasic into a ClassBasicMapper.
We did run into some issues however:
As you can already guess, we end up with a LOT of interfaces. More than you want.
Sometimes a field exists across versions, but has different (enum) values. Our domain model would have the superset, with an attribute specifiying which values were valid for which versions.

Serialization and object versioning in C#

If I want to serialize an object I have to use [Serializable] attribute and all member variables will be written to the file. What I don't know how to do versioning e.g. if I add a new member variable (rename a variable or just remove a variable) and then I open (deserialize) the file how can I determine the object/file version so I can correctly set the new member or take some kind of migration? How can I determine that the variable was initialized during the load or not (ignored by deserializer).
I know that there are version tolerant approaches and I can mark variables with [OptionalField(VersionAdded = 1)] attribute. If I open an old file the framework will ignore this optional (new variable) and it will be just zero/null. But again how can I determine if the variable is initialized by load or it was ignored.
I can write the class/object version number to the stream. Use the ISerializable approach and in the constructor(SerializationInfo oInfo, StreamingContext context) method read this version number. This will exactly tell me what is the class version in the stream.
However I expected that such kind of versioning is already implemented by the streaming framework in C#. I tried to obtain the Assembly version from the SerializationInfo but it is always set to current version not to the version which was used when the object was saved.
What is the preferred approach? I found a lot of articles on the net, but I could not find a good solution for this which addresses versioning...
Any help is appreciated
Thanks,
Abyss
Forgive me if some of what I write is too obvious,
First of all, please! you must stop thinking that you are serializing an object...
That is simply incorrect as the methods which are part of your object are not being persisted.
You are persisting information - and so.. DATA only.
.NET serialization also serializing the type name of your object which contain the assembly name and its version, so when you deserialize - it compares the persisted assembly information with the type that will be manifested with the information - if they are not the same it will return an exception.
Beside the versioning problem - not everything can be serialized so easily.. try to serialize a System.Drawing.Color type and you will begin to understand the problems with the over simplistic mechanism of .NET serialization.
Unless you plan to serialize something really simple which has no plans to evolve I wouldn't use the serialization mechanism provided by .NET.
Getting the focus back to your question, you can read here about the versioning ignorance ability:
http://msdn.microsoft.com/en-us/library/ms229752(v=vs.80).aspx which is provided for BinaryFormatter.
You should also check XML Serialization which has some nice abilities, but the biggest benefit is that you getting an XML which is Human readable so your data will never be lost even if you had complication with the versioning of your types.
But finally, I recommend you either use Database with Entity Framework to persist your data or write your own flat file manager.. while EF is very good for most solutions, sometime you might want something lighter to persist something very simple.
(my imply is that I can no longer see a solution where .NET serialization can be relevant.)
I hope this helps, Good luck.

what problem does the serialization proxy pattern solves that the serialization pattern doesn't solve?

I need to be able to serialize a class into a string, and I know of 2 patterns:
1) (normal) Serialization pattern
2) Proxy Serialization pattern
I've read http://lingpipe-blog.com/2009/08/10/serializing-immutable-singletons-serialization-proxy/ (the only website in google that talks about the proxy-serialization pattern) and still cant find the advantage or benefit of using this pattern. Could someone explain what exactly is the proxy serialization pattern, or rather exactly what problem does the proxy-serialization pattern solves that the normal-serialization pattern doesn't solve?
Default serialization:
Creates multiple instances of classes supposed to be singletons on deserialization
Supposedly has issues with changed in-the-fly deserialized objects (huh?)
Second point is arguable. Who has changed the data of the bytestream? If it could happen we have a bigger issue than deserialization: security. Signed/encrypted streams would solve the serialization issue too.
First one is real one. Serialize the same singleton a few time, deserialize on the other side, and oops! you have multiple singletons (multitones?). That problem though is IMHO easier solved by making a singleton out of Enum, then JVM will enforce the single instance itself.
UPDATE
As was pointed out by Steve B, the blog poster perhaps misunderstood/misrepresented what did he read. Instead of "serialize, tweak bytes, then deserialize" one should read "serialize, deploy new version of the class, deserialize". Yes, this is known problem, and Externalizable interface allows one to solve it neatly by taking a full control over the class serialization, so even the later version of the class can deserialize own data from a stream created by a previous versions (if it possible at all).

How do I safely use an obfuscator?

When I attempt to use dotfuscate on my application, I get an application error when I run it.
Dotfuscator (and all obfuscators) are typically safe to run on an application, but they do occasionally cause problems. Without specific details of your problem, it's difficult to diagnose.
However, one common problem with obfuscators is when you mix them with reflection. Since you're changing the type names, but not strings, any time you try to reflect on objects with a specific string name, and use the reflection namespace to construct objects, you'll likely have problems.
Most of the problem I have encountered with obfuscation revolve around types that can't have their name changed, because something needs to reflect on them (your code or the runtime).
for example if you have a class that is being used as a web service proxy, you can't safely obfuscate the class name:
public class MyWebServiceProxy : SoapHttpClientProtocol
{
}
Also some obfuscators can not handle generic methods and classes.
The trick is you need to find these types and prevent the obfuscater from renaming them. This is done with the Obfuscation attribute:
[global::System.Reflection.Obfuscation(Exclude=true, Feature="renaming")]
Another thing that can be a problem with obfuscators is serialization using BinaryFormatter, since it changes the field names. I have some users who use protobuf-net for serialization on their obfuscated code for this reason.

.NET: with respect to AssemblyVersion, what defines binary compatibility?

What changes to a strong-named assembly necessitate a change in AssemblyVersionAttribute? Clearly, changing the public api in a way that could require a client to have to make a code change requires an increase in AssemblyVersion. But what about changes to the public API that don't require code changes in the client? For instance:
the addition of a public class or interface?
the addition of a public member to a public class or interface? (EDIT: drscroogemcduck correctly points out below that adding a member to an interface would hose all implementors. Silly me.)
an increase of visibility of a class member?
There's got to be definitive documentation of this somewhere on MSDN (or, knowing MS, on some MSSE's personal blog). But I simply cannot find it. Please help!
In response to Martijn's bounty:
The best reference on binary compatibility is on the community Wiki.
A definite guide to API-breaking changes in .NET
It's pretty easy... as long as Types remain unchanged (in their public or protected layout) and method signatures are not changed (adding methods or types is fine), the JIT should be able to link the DLL just fine.
That said, I think that even if it does work you should not do this. Make a new version and use a policy to map the old version to the new one, if required. Otherwise you drive yourself straight back to DLL hell... and I'm pretty sure you don't want that.
adding methods to an interface shouldn't be fine because old providers won't implement the new methods.
Microsoft adds new methods/classes in .NET libraries in service pack releases without changing AssemblyVersion (still 2.0.0.0 / 3.0.0.0). Microsoft only changes the AssemblyFileVersion.
For example, In .NET 2.0 SP1, DateTimeOffset struct was added.
Should this practice be recommended to us because Microsoft do this?
It is confusing.

Categories