-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
FormatterServices.GetUninitializedObject
replacement?
#17073
Comments
@eiriktsarpalis, I think it would be great if we could come up with a solution for scenarios like yours without resorting to using/exposing things that amount to internal/private APIs. The fact that .NET Framework's binary serialization uses internal/private state has been a constant compatibility and security headache. And so I would be interested in understanding why you think we need to construct unititialized objects (logically not a public API) as opposed to requiring that serializable types expose a public constructor that could be used for serialization (either default or parameterized). |
@KrzysztofCwalina granted, this is certainly something which touches internals. But the same thing could be said of any library that uses some form of reflection/binding flags to access internals. There are very few useful serialization libraries out there that do not rely on this. Like I said, my primary concern is closure serialization. Let's consider the introductory example from the Mobius project: var lines = sparkContext.TextFile(@"hdfs://path/to/input.txt");
var wordCounts = lines
.FlatMap(s => s.Split(' '))
.Map(w => new KeyValuePair<string, int>(w.Trim(), 1))
.ReduceByKey((x, y) => x + y)
.Collect(); In order to be able to distribute the above workflow across a Spark cluster, it is necessary to be able to serialize a considerably complex object graph that includes lambda expressions. Depending on the language/library implementation, such lambdas are typically encoded using internal, compiler-generated classes which lack accessible constructors or serialization attributes. A good example are F# lambdas which are serializable abstract classes. I do not see how language designers could ensure compiler generated types are serializable without unnecessarily polluting the public API of the generated assembly. |
The thing is that when people use private reflection, they are more likely to be aware that their code might not work at some point, as we don't guarantee the shape of internal/private types to be the same between versions/frameworks. But for serialization, we do try very hard to be cross version compatible. Public APIs are the way we describe compatibility guarantees of .net types, and it would be great if serialization used the same mechanism. It would make it easy to reason about serialization compatibility. Good point about polluting APIs. I think there will be some types that might not want to hide some of their public APIs. But I wonder if that could not be addressed with EditorBrowsable attributes and/or serialization proxy types/APIs. |
I agree, reflection-based serialization that relies on internal class representations stinks. But for lack of a viable alternative for many classes that exist out there, it's immensly useful in some applications. I get how this can be dangerous looking at it from the point of view of an asp.net developer, but there are other applications in .NET than just the web. The serialization that I'm interested in is of the non-persistable, non-version tolerant, non-heterogeneous communication variety. As mentioned earlier, there are quite a lot of important Microsoft projects that rely on this as well. I don't use BinaryFormatter for my projects and I agree that it is broken and obsolete. What I'm basically asking for is please let us build our own general-purpose serializers on top of CoreCLR. I get it, reflection is ugly, it invalidates accessibility modifiers and is an all-around security liability. But if used responsibly it lets us write some amazing libraries. It allows us to do runtime metaprogramming and gets us places where the type system on its own simply cannot. |
In any case, the removal of the (arguably bad) |
@KrzysztofCwalina the removal of |
|
@zhenlan, you can see dotnet/corefx#8133 on some my current thinking around this issue. I will look into ISerializable as well, but I think it's a bit more tricky. The two APIs that I proposed we add are general purpose enablers. ISerializable is binary serialization and it comes with its baggage. But we really want to unblock the community, and so nothing is off the table. |
@KrzysztofCwalina I should point out that ISerializable is not tied to binary serialization (or any serializer/serialization format for that matter). It merely provides an abstraction for serializer implementations to extract and reconstruct objects using SerializationInfo. |
@eiriktsarpalis, when I said "binary serialization", I meant the specific technology we have in .NET Framework. I do not have anything against serializing to a binary format. I actually think it's great/efficient. As a side note, do you know of any other serializers using ISerializable besides the serializers in .NET Framework? i.e. I wish ISerializable was an abstraction, but it does not seem to be to me. StreamingInfo is quite locked and does not let me access the data in an out-of-band library (i.e. library that does not use internal framework APIs). |
It does, json.net implements support for it and so does our own serializer implementation, FsPickler which supports binary, json, bson and xml serialization formats. SerializationInfo is perfectly accessible by third-party libraries, it's merely a special type of key/value accumulator. |
Yeah, I guess you are right. I was just hoping to be able implement my own SerializationInfo and intercept the calls to AddValue/GetXxx. |
Just to confirm what @eiriktsarpalis said, |
Hi, In a nutshell, I'm serializing the following private fields from These are the relevant portions (without any extra optimizations, as this is not production code yet) of the steps I took to serialize exceptions in Orleans:
Just as FYI, this is in an exploratory branch I have here: https://github.com/jdom/orleans/blob/coreclr-multi/src/Orleans/Core/ExceptionSerializer.cs |
FormatterServices.GetUninitializedObject has been added to .NET Core 1.2. |
I'm author of FsPickler, a multi-format message serialization library intended as a replacement to BinaryFormatter. The focus of the library is serialization of closures, which means that I need to support things like subtyping and internal, compiler-generated classes that often have no accessible constructors or serialization attribute annotations.
I would be interested in porting FsPickler (and its father project, mbrace) to CoreCLR, however there are many obstacles, mostly related to deprecated APIs. The component I'm more concerned about is the
FormatterServices.GetUninitializedObject
method which is used for instantiating objects without relying on a parameterless constructor. This is crucial for us since many closure types (particularly F# lambdas) do not come with such constructors.Do you have any plans for replacing this with equivalent functionality?
/cc https://github.com/dotnet/corefx/issues/6564#issuecomment-212620200 https://github.com/dotnet/coreclr/issues/2715
The text was updated successfully, but these errors were encountered: