Comments (17)
I see, that makes sense.
About the code, what I've got is something very simple for my specific use case, just needed something quick and dirty, but you can gladly have it:
public static void ToFile(this XmlDocument doc, string path)
{
using (var xmlTextWriter = new XmlTextWriter(path, new UTF8Encoding(false)))
{
xmlTextWriter.Formatting = Formatting.Indented;
xmlTextWriter.IndentChar = '\t';
xmlTextWriter.Indentation = 1;
doc.Save(xmlTextWriter);
}
}
public static T DeserializeFromFile<T>(this ExtendedXmlSerializer xmlSerializer, string path)
{
var xml = File.ReadAllText(path);
return xmlSerializer.Deserialize<T>(xml);
}
public static void SerializeToFile(this ExtendedXmlSerializer xmlSerializer, object o, string path)
{
var xml = xmlSerializer.Serialize(o);
var xmlDocument = new XmlDocument();
xmlDocument.LoadXml(xml);
xmlDocument.ToFile(path);
}
So you can see in my case I'm not doing anything specifically with either Xml/Text Reader/Writer
from home.
Definitely... for v2 we actually have the serializer methods accept a stream. Will that be sufficient? Or do you think you'll need an extension method for file as well? I think the best approach is to keep it open to stream, and allow consumers to fill in implementation details such as file. But definitely open to feedback around this. :)
from home.
For my purposes, that's plenty. Though I would suggest maybe keeping it inline with what XmlSerializer offers: Stream, TextReader/TextWriter and XmlReader/XmlWriter.
from home.
Getting an XmlWriter would make modifying the XML much easier for example. It's what I'm currently using to do the indentation.
from home.
Ah ok... TBH I am still confused between all the options in how XmlSerializer allows you to initialize. I tried to dig into it but it seems as if they really do use all 3 of those. If you know of any resources that explain why there are 3 (or know outright) I would be happy to check it them out.
We could create a Using(XmlWriter)
method to the ConfigurationAPI. Or maybe Using(()=>XmlWriter)
as a new XmlWriter
is created for each serialization. The same could also be used for XmlReader
, too.
from home.
OK with v2 mostly complete we can revisit this again. We currently use stream, but the ask here is for text/xml reader/writer. We do use a factory for creating xmlreader and xmlwriters. You can see that here.
It would be easy enough to create a new serializer extension that creates a new implementation via use of the stream or otherwise.
So something like:
class XmlFactoryExtension : ISerializerExtension
{
public IServiceRepository Get(IServiceRepository parameter) => parameter.Register<IXmlFactory, MyFactory>();
void ICommand<IServices>.Execute(IServices parameter) {}
}
class MyFactory : IXmlFactory
{
public IXmlWriter Create(Stream stream, object instance)
{
...
}
public IXmlReader Create(Stream stream)
{
...
}
}
Then using it as such:
var serializer = new ExtendedConfiguration().Extend(new XmlFactoryExtension()).Create();
I am hesitant to add more API surface than is required, as I myself find the different ways of creating a document/instance very confusing, but I am open to feedback as always.
How does this suggested approach look/work for everyone?
from home.
The ask here was for Serialize and Deserialize methods to accept other parameter types (namely those that are already supported by the default XmlSerializer - TextReader/TextWriter and XmlReader/XmlWriter).
Maybe I misunderstood it, but I think that what you suggested goes in a different direction and is more complicated to use than creating simple overloads for Serialize/Deserialize which accept those parameter types?
from home.
What kind of function I can do with it? I don't know if it is useful for users. There is some real example?
from home.
OK so it seems that this all really hinges on my ignorance around the connections between Xml/Text* and Stream, so you'll have to forgive me here. Taking another peak, it appears you can create a System.Xml.XmlWriter
by either a stream or TextWriter
. I think what I got caught up in was trying to find the actual implementation to where the stream was used (different matter altogether).
In any case, our current design is suboptimal. It is currently as such:
public interface IExtendedXmlSerializer
{
void Serialize(Stream stream, object instance);
object Deserialize(Stream stream);
}
When it sounds like it should be this:
public interface IExtendedXmlSerializer
{
void Serialize(System.Xml.XmlWriter stream, object instance);
object Deserialize(System.Xml.XmlReader reader);
}
and a set of extension methods as such:
public static class Extensions
{
public static void Serialize(this IExtendedXmlSerializer @this, Stream stream, object instance)
=> @this.Serialize(System.Xml.XmlWriter.Create(stream), instance);
public static void Serialize(this IExtendedXmlSerializer @this, TextWriter writer, object instance)
=> @this.Serialize(System.Xml.XmlWriter.Create(writer), instance);
public static object Deserialize(this IExtendedXmlSerializer @this, Stream stream)
=> @this.Deserialize(XmlReader.Create(stream));
public static object Deserialize(this IExtendedXmlSerializer @this, TextReader reader)
=> @this.Deserialize(XmlReader.Create(reader));
}
How does that look, @FaustoNascimento? That actually would not be too much work and I appreciate your patience/persistence in helping me to see this. Especially since this could be a breaking change it's better to do it now before we actually release anything to Nuget. :)
from home.
@wojtpl2 this is actually a fundamental issue with the design as the lowest common denominator here is the System.Xml.XmlWriter/Reader. It is sort of complicated by the fact that I originally designed it with it being format-agnostic, but I think it's pretty clear at this point that is something that is probably better for v3.
So something like this (in v3):
public interface ISerializer<TReader, TWriter>
{
void Serialize(TWriter writer, object instance);
object Deserialize(TReader reader);
}
public interface IExtendedXmlSerializer : ISerializer<System.Xml.XmlReader, System.Xml.XmlWriter> {}
from home.
Careful with creating a XmlWriter
from a TextWriter
- if I'm not mistaken, you cannot easily change the encoding used by the TextWriter
and it defaults to UTF16, so the header of the XML will state it's encoded using UTF16, as oppose to UTF8 (I found this out the hard way, when I was trying to create an extension method for EXS to Serialize directly to file).
Instead of having extension methods, would it not be easier to create overloads?
Edit
Sorry, just realized you're suggesting the extension methods as a temporary fix for v2, with v3 then being done differently. Still, with the overloads just be careful of how the XmlWriter
is created.
from home.
Ah, it's definitely open to discussion, even for v3. I will share my perspective and I would like to hear your thoughts on it.
From my view, my concern is always about exposing surface for any component that I write. Not just for me, but for any consumers of that component. Here is a good thread about this very issue that was encountered during the development of v2 (see point 2).
In that case we're talking about ~30 methods that can boiled down to a great deal less. Here we're talking about the same thing, except in the opposite direction. It's still taking from 2 to 6, but that means every implementor of that interface will have to create an implementation for each and every one of those methods each and every time.
Now in the case of some specialized knowledge of ensuring correct instantiation of objects, then that might change things a bit, but I would probably err on encapsulating that in a factory which is then called by the extension method.
I so guess the point is that for every method on the interface, maximum effort should be made to ensure that it isn't overlapping with other methods on that interface. I am definitely open to discussion on this and would like to hear your thoughts about it.
Also, if you have any finalized code that you are using that you would suggest in instantiating an XmlWriter, I would be interested in that. In fact I believe I saw some bug reports on the new Roslyn CPS project system for Visual Studio that was talking about the UTF16 issue.
from home.
Great! I will look into it and let you know.
from home.
Alright, I have been checking this out. A few questions for you, @FaustoNascimento:
- Is there a reason for using
new XmlTextWriter
vs.System.Xml.XmlWriter.Create
? - Are you aware of
File.Create
? Using this, you could write to a file without the need of usingXmlDocument
. Additionally, this is supported by .NETStandard1.6 whileXmlTextWriter
oddly isn't. - Looks like the code here is using a
XmlTextWriter
here and not aTextWriter
, and wanted to verify. I am interested in knowing if there was anything you landed on with the utf8 vs utf16 as a solution. Or maybe you just ended up ditchingTextWriter
altogether?
After spending more time than I expected here, I'd also like to reiterate the drive/desire for simplicity. I basically took about an hour (again LOL) of my time to try to wrap my mind around all the ways you can create an XmlWriter
, and the associations/connections between all the components. For instance, proper closing/disposing of each item (and wrapped item) and additionally with how XmlWriterSettings
plays in with this (it doesn't when you use a new XmlTextWriter
).
I think this was also another goal achieved by simply using Stream
. Nonetheless, I see the value in exposing the root denominator here, especially if we have a strategy for keeping things simple via the proposed methods above.
from home.
- Yes, it's called dumbness. Or as prefer to label it for myself... "lack of sleep". Not sure anyone will buy that though...
- I think the reason why I used the
XmlDocument
here was simply because I was already using theXmlTextWriter
so it sort of just fit in nicely. - If I recall correctly, I started with a
TextWriter
, but that's when the encoding issues occurred, so I just ditched it altogether.
There's no doubt that the code above can be improved, as I said not quite sure just how much of that is usable.
from home.
Ha, sounds good, @FaustoNascimento. Thanks again for your contribution. 👍
So I went ahead and got in the extension methods. You can now use Stream/Xml/Text/Writer/Reader with ExtendedXmlSerializer. 🎉
Unfortunately (or fortunately depending on your perspective), it did cover some issues with performance. I will make a new issue for this. Hopefully we can release a new pre-release soon so that you can try this out. I will be closing this issue for now. Please feel free to re-open/open a new issue if you have trouble with the features as designed.
from home.
Ah @FaustoNascimento looks like the latest version is deployed for better or for worse here if you'd like to try it out:
https://www.myget.org/feed/wojtpl2/package/nuget/ExtendedXmlSerializer
from home.
Related Issues (20)
- Remove netcoreapp3.1 HOT 2
- Update build keys HOT 2
- Update Documentation Key HOT 2
- Circular dependencies detection problem 2 HOT 8
- Address Warnings HOT 1
- (De)serialization of objects with property-name same as object-name stopped working correctly since V3.2 HOT 11
- Target Instances Remain In Activation HOT 1
- Address Warnings HOT 1
- Dictionary/List serialization issue/question HOT 6
- Sprache.ParseException? HOT 4
- ShouldSerialize is not working. HOT 2
- DateOnly type not serialized HOT 8
- Will Configuration for a base class automatically apply to its derived classes? HOT 13
- Deserialization of inherited class with different namespaces not possible with Migration HOT 8
- Deserialization issue with inherited class with different namespaces and Migration HOT 2
- Update NuGet Key HOT 1
- Update GitHub API Token HOT 1
- API Key HOT 1
- Update Deploy Key HOT 2
- Update Script for RSA HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from home.