Closed damageboy closed 9 years ago
The F# compiler will automatically attach the Serializable attribute to most type definitions. To mark a type as non-serializable in F# you need to explicitly disable this behaviour:
[<AutoSerializable(false)>]
type Foo = class end
FsPickler will treat such types as non-serializable unless other serialization schemata are explicitly specified. For more information have a look here: http://msdn.microsoft.com/en-us/library/ee370515.aspx
I should have specified that I'm using this to serialize a bunch of C# classes as well..
In addition, if I read the code properly (and I might not) if a class that is serializable but has a field pointing to a non-serializeable class, it throws an NonSerializableTypeException, with no possibility of skipping that field.
What I would like is to supply types that FsPickler will treat as NonSerialized according to their type instead of throwing an exception.
C# shouldn't be a problem, since classes do not carry the Serializable attribute by default.
As regards non-serializable fields, these can always be ignored by attaching the NonSerialized
attribute.
See also http://msdn.microsoft.com/en-us/library/axwwbcs6(v=vs.110).aspx or http://msdn.microsoft.com/en-us/library/72hyey7b(v=vs.110).aspx
For a more detailed example, http://stackoverflow.com/a/635662
In general, I would recommend against field based serialization, as it tends to be implementation sensitive. You could have a look at either ISerializable or DataContract. I have written an overview of the available options here: http://nessos.github.io/FsPickler/overview.html
I'm probably not explaining myself properly. I have two problems, that could be solved by marking types (not fields!, like you suggest) as non-serializable (somehow):
I could in theory go for the DataContract path, but then I would have to start sprinkling DataMemeber fairy dust on hundreds of members to explicitly include each member in each and one of my classes in the hierarchy, instead of marking the 5-6 types I would like to skip instead...
Is my problem statement clearer now?
Ok, I think I understand your problem now. I cannot say it is clear to me what is the best solution.
By the way, what serializer are you currently using and how do you solve this issue? Most libraries that I know of ivariably fail when trying to serialize objects with nonserializable fields.
Hi, I currently use protobuf, but instead of proviting protomember/protoignore attributes all over the place, I have one class that through reflection uses the "ad-hoc" mode of protobuf and build a protobuf-net RuntimeTypeModel, which allows me to decide at runtime what/how to serialize...
Here's another idea, while scanning the types in FsPickler, it shouldn't be too hard to test against external "attributes". .NET supports this conecpt through System.ComponentModel.TypeDescriptor where you can, at runtime "register" attributes for a specific type, i.e.:
TypeDescriptor.AddAttributes(typeof(SomeClassIWantToSerielize), new[] { new PickleMeAttribute() });
TypeDescriptor.AddAttributes(typeof(SomeClassINeverWantToSerielize), new[] { new DontPickleMeAttribute() });
That way, the Picker reflection code has another source of "meta-data" to consule while discovering types. This adds a dependency between FsPickler -> System.ComponentModel, but the code doing the serialization can add any class-level attribute @ runtime, without inflicting any dependencies on the code where the types to be serialized are residing...
This sort of approach works better with the existing code base, I think, in the sense that it's just another satatic, globally available registry of meta-data, much like reflection to consult while going over the type hierarchy? Does that make sense to you in FSPickler?
Original versions of the library did carry a custom pickler plugging mechanism that could be set at runtime. You could define you own serialization/deserialization methods (in your case, no action on serialization - always returning null on deserialization) and override the default provided by the pickler generation mechanism. This had the problem of lacking "referential transparency": for instance, two independent libraries collocated in the same process registering conflicting serializers for the same type. This is a legitimate concern for the type of software that we make, so we initially addressed it by forcing discrete "pickler universes" for every consumer of the FsPickler library. This solution was particularly heavyweight and introduced a new class of errors in which a fresh pickler cache could be created upon every serialization/deserialization. The current version of the library has deliberately done away with all that and enforces a global, "referentially transparent" pickler generator in type definitions act as the sole source of serialization information. The advised way in which this can be circumvented is either through explicit use of pickler combinators or wrapper types, although admittedly these are methods more suited to F# than C#.
I'll certainly think more about this, since your concern is definitely legitimate. In the meantime, do you think that IgnoreDataMemberAttribute
would convenience you? It is relatively straightforward to implement atm.
@damageboy I just added support for the IgnoreDataMemberAttribute
in 7afe9ea4a7e67456cc61f868b40e57cbe8436f2e. Let me know if this helps with your problem.
This has been partially addressed as of 1.2.5, closing.
Hi, I'm trying to dump my current serialization setup for a a large object graph of types I have.
The way I've started to work with FsPickler is to start sprinkling Serializable attributes all over my code. This it perfectly acceptable, but the problem I'm experiencing is with non Serializeable types.
I would like to be able to somehow inform FsPickler that a type is not serializable (rather than marking each field in other classes that is of that type).
I cannot seem to find this ability in the current code in FieldPicklers.fs or anywhere else in FsPickler.
I would like to work on this, but I thought that it would be better to start some sort of a discussion on how these things should be done.
I can see two approaches:
In addition to what I've outline in (2), the same idea could be applied for the use of SerializableAttribute, i.e., another Set/List could be supplied that would contain types that SHOULD be treated as Serializable even if they are not marked as such through the Serializable attribute. This will have the additional advantages:
Any thoughts? Is the direction of adding Sets of Types to the (de)serialization api-points acceptable?