• Visitors can check out the Forum FAQ by clicking this link. You have to register before you can post: click the REGISTER link above to proceed. To start viewing messages, select the forum that you want to visit from the selection below. View our Forum Privacy Policy.
  • Want to receive the latest contracting news and advice straight to your inbox? Sign up to the ContractorUK newsletter here. Every sign up will also be entered into a draw to WIN £100 Amazon vouchers!

.NET deserializng an unknown object type from XML

Collapse
X
  •  
  • Filter
  • Time
  • Show
Clear All
new posts

    .NET deserializng an unknown object type from XML

    I have a function which needs to deserialize an XML string, but it doesn't at this point know the object type.

    So I get a string like:-

    "<?xml version="1.0" encoding="utf-16"?>
    <OneClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <SomeThing>Serializer.OneClass &lt;--This class type</SomeThing>
    </OneClass>"

    Or maybe:-

    "<?xml version="1.0" encoding="utf-16"?>
    <TwoClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <SomeThing>Serializer.TwoClass &lt;--This class type</SomeThing>
    </TwoClass>"

    And I want to end up with a "OneClass" or a "TwoClass".

    I can do this by creating an xmlDocument, loading the XML, getting the documentelement.name, mapping that to a type via configuration information, and this then gives me the type which I can create an xmlSerializer from. Then I can deserialize it.

    But surely there must a better way.

    Stuffed if I can find it though. Any suggestions?

    Cheers.

    #2
    Would deserializing against an interface do the job? Or are they completely random objects?

    Comment


      #3
      If you are controlling the serialization end too, you might be better off using the NetDataContractSerializer Class instead.

      http://msdn.microsoft.com/en-us/libr...erializer.aspx

      Since this serializer embeds the types and namespaces of the serialized objects into the XML, it does not need to know the type to deserialize them back into different objects.

      Comment


        #4
        Do you know how the objects were serialised?
        E.g. did it use a standard .NET serialisation method or a custom written one?

        Comment


          #5
          Originally posted by DimPrawn View Post
          If you are controlling the serialization end too, you might be better off using the NetDataContractSerializer Class instead.

          http://msdn.microsoft.com/en-us/libr...erializer.aspx

          Since this serializer embeds the types and namespaces of the serialized objects into the XML, it does not need to know the type to deserialize them back into different objects.
          Unfortunately I'm not controlling the serialization end.

          It's not too much of a problem, there are only about 10 different messages. Pro-tem I guess I'll just have to parse them into an XML document and switch based on the name.

          If I can be bothered I'll add something to the config file to give me the name of the root node and the type to deserialize it to. I can then get the type with reflection and create the deserializer.

          It just "feels" such a mess.

          Cheers.

          Comment


            #6
            Sounds like you have design issues.

            How comes you are not controlling the serialization?
            Why don't you know what type the file contains until you open it?
            Why are you having to resort to this bodge?

            A crap design leads to crap bodges like you are contemplating.

            Comment


              #7
              Originally posted by DimPrawn View Post
              Sounds like you have design issues.

              How comes you are not controlling the serialization?
              Why don't you know what type the file contains until you open it?
              Why are you having to resort to this bodge?

              A crap design leads to crap bodges like you are contemplating.
              It's interfacing to a system which simply sends an XML message over a TCP socket. The type is defined by the root node of the XML message. I didn't design that bit, I just have to interface with it.

              The answer seems to be (with .NET 2) to create an array of types, get an array of serializers, ask each one whether it can deserialize the secified packet. That saves most of the messing about with trying to extract the root node name to infer the type information.

              Comment


                #8
                Originally posted by ASB View Post

                The answer seems to be (with .NET 2) to create an array of types, get an array of serializers, ask each one whether it can deserialize the secified packet. That saves most of the messing about with trying to extract the root node name to infer the type information.
                Why you say "ask" do you really mean try and catch exceptions?

                That's a very slow process and not really a good pattern.

                From a blog:

                Anyway, C# is a little more “roll-up-your-sleeves” and solve your own problem, so there is no equivalent IsNumeric function in C#. This former student of mine asked if the following was an acceptable alternative:

                public static bool isNumeric( string strText )
                {
                try
                {
                int i = int.Parse( strText ) ;
                return true ;
                }
                catch
                {
                return false ;
                }
                }

                What's wrong with this picture? This is classic lazy-programming (or, in this case, just inexperienced programming) because the person knows enough about C# to use try{}catch{}, but is using it inappropriately. Exceptions are for exceptional situations -- not for avoiding some real thinking through the issue. Catching exceptions is hard work on your programs and performance will really suffer: this try{}catch{} isNumeric() function is over 2,000 times slower than this alternative:

                public static bool isNumeric( string strText )
                {
                char[] chars = strText.ToCharArray() ;
                for ( int i = 0; i < chars.Length; i++ )
                {
                if( !Char.IsDigit( chars[ i ] ) ) //could also explore IsNumber
                {
                return false ;
                }
                }
                return true ;
                }

                Comment


                  #9
                  Originally posted by DimPrawn View Post
                  Why you say "ask" do you really mean try and catch exceptions?

                  That's a very slow process and not really a good pattern.

                  From a blog:
                  No I mean ask. CanDeserialise returns a boolean indicating if it can deserialise it. I don't know how it's implemented but I imagine it is reasonably efficient.

                  Comment


                    #10
                    Originally posted by ASB View Post
                    No I mean ask. CanDeserialise returns a boolean indicating if it can deserialise it. I don't know how it's implemented but I imagine it is reasonably efficient.
                    No it uses the root element name and namespace:

                    internal bool CanRead(int methodIndex, XmlReader xmlReader)
                    {
                    TempMethod method = this.methods[methodIndex];
                    return xmlReader.IsStartElement(method.name, method.ns);
                    }


                    So should be fine.

                    Comment

                    Working...
                    X