Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In C#, why can't I pass a StringReader to a method with a Stream parameter?

Tags:

c#

.net

xml

In .net 4 and C#. I've implemented a static method to deserialize an XML stream into an object. This is only one xml format going into one object, so I'm not trying to do anything fancy with that. Since I can get this XML content in a variety of ways, I thought I'd make the parameter passed to the static method a Stream object. I'd thought that it would then take any object derived from base class Stream -- like FileStream, MemoryStream, StringReader, etc.

It works fine when I pass it a FileStream object, but not when I pass it a StringReader.

My static method:

    public static MatchObj DeserializeMatch(Stream srXml)
    {
        XmlSerializer xs = new XmlSerializer(typeof(MatchObj));
        MatchObj mObj = (MatchObj)xs.Deserialize(srXml);

        return mObj;
    }

It works with a FileStream:

        MatchObj objReply;
        using (FileStream fs = new FileStream(Server.MapPath("/App_Data/Match.xml"), FileMode.Open))
        { 
            objReply = MStatic.DeserializeMatch(fs);

            fs.Close();
        }

But not a StringReader:

StringReader sr = new StringReader(Request.Form["mXML"]);
MatchObj objReply = MStatic.DeserializeMatch(sr);

The build error is: "cannot convert from 'System.IO.StringReader' to 'System.IO.Stream'"

Which in and of itself makes sense, but I thought that since StringReader implements TextReader, that it counted as Stream? XML Deserializer works fine with either.

I've worked around it simply by overloading that method to take a StringReader, but I hate to see what I thought was an elegant idea fall apart. Any ideas on why this doesn't work, and/or a way to make it work?

like image 334
Patches Avatar asked Dec 17 '22 19:12

Patches


2 Answers

Here is the inheritance hierarchy of a StringReader...

System.Object 
  System.MarshalByRefObject
    System.IO.TextReader
      System.IO.StringReader

I would suggest putting Request.Form["mXML"] into a MemoryStream instead.

This might work (untested)...

var xmlBytes = Encoding.UTF8.GetBytes(Request.Form["mXML"]);
var ms = new MemoryStream(xmlBytes);
var reply = MStatic.DeserializeMatch(ms);
like image 179
Brian Avatar answered Apr 27 '23 16:04

Brian


Well, technically, (but obviously) Because neither StringReader nor TextReader derive from Stream.
Perhaps more informatively, a Stream is the abstract base class that represents a sequence of Bytes. All the [Something]Reader and [Something]Writer classes are designed to read or write to/from a Stream, they are not themselves Stream objects. It is arguably true, however that these classes are all very poorly named and contribute to the misunderstanding that many developers have about this entire topic.

like image 30
Charles Bretana Avatar answered Apr 27 '23 15:04

Charles Bretana