hubFS: THE place for F#

. . . are you on The Hub?
Welcome to hubFS: THE place for F# Sign in | Join | Help
in Search

Dynamic cast to Interface

Last post 10-25-2007, 17:54 by dcampbell. 4 replies.
Sort Posts: Previous Next
  •  09-12-2007, 7:41 3616

    Dynamic cast to Interface

    The recommended practice for System.Xml.XmlReader is to use the static Create method to create instances. As a consequence one has to use a dynamic cast in order to get hold of the System.Xml.IXmlLineInfo interface. I just can't figure out how to do this in F#. Could maybe somebody help me translate the the following C# snippet to F#?

    System.Xml.XmlReader reader = System.Xml.XmlReader.Create(
        new System.IO.StringReader("<doc></doc>"
    )
    );
    System.Xml.IXmlLineInfo li = reader as System.Xml.IXmlLineInfo;
    System.Console.WriteLine(li.LinePosition);

  •  09-12-2007, 8:41 3617 in reply to 3616

    Re: Dynamic cast to Interface

    Hi,
    the following code should work:


    #light

    let reader =
      System.Xml.XmlReader.Create
        (new System.IO.StringReader("<doc></doc>"))
    let li = ((box reader) :?> System.Xml.IXmlLineInfo)
    System.Console.WriteLine(li.LinePosition)

    The problem that you probably had is that casting 'reader' directly to 'System.Xml.IXmlLineInfo' using 'reader :?> System.Xml.IXmlLineInfo' doesn't work - I'm not sure if my understanding is correct, but I would say that the :?> operator requires the target type to be inherited from the type of the value on the left side (so having B inherited from A and a instance of (static) type A you could write 'a :?> B'). For dynamic casts to interface types this may be an unnecessary restriction, but I'm not sure if there is any other good reason.

    Anyway, the solution is converting the 'reader' to a type obj, which is a base for all .NET types and it is possible to use dynamic cast to any other type from the obj type. Converting any F# value to obj can be done using the 'box' function.


    Tomas Petricek (Blog), C# MVP
    My book: Real-world Functional Programming in .NET
  •  09-12-2007, 9:01 3618 in reply to 3617

    Re: Dynamic cast to Interface

    Hi tomasp,

    your solution works great! Thanks for your help.

    :?> was among the things I tried without success. Maybe somebody else can shed some light on why the boxing is necessary...

  •  09-12-2007, 17:24 3621 in reply to 3618

    Re: Dynamic cast to Interface

    Hi all,

    I agree this is an unecessary language limitation. Dynamic casts to interfaces should be permitted usig ":?>" without using "box".

    We'll fix this.

    Thanks

    Don

     

  •  10-25-2007, 17:54 3871 in reply to 3618

    Re: Dynamic cast to Interface

    Stephan,


    I'm pretty sure that this is because System.Xml.XmlReader.Create() returns an instance of System.Xml.XmlTextReaderImpl that is upcast to an XmlReader. The problem is that, XmlReader does not implement IXmlLineInfo -- XmlTextReaderImpl does. So, the compiler cannot verify that "reader" actually implements IXmlLineInfo because it is of type XmlReader.

    Hopefully, :?> will be fixed soon. Until then, you could define a function that handles the box for you. This should do the trick:

    #light

    let dynamic_cast o = (box o) :?> 'a

    let reader =
      System.Xml.XmlReader.Create
        (new System.IO.StringReader("<doc></doc>"))
       
    let li: System.Xml.IXmlLineInfo = dynamic_cast reader

    System.Console.WriteLine(li.LinePosition)


    Regards,
    Dustin Campbell
    Microsoft C# MVP
    http://diditwith.net
View as RSS news feed in XML
Powered by Community Server, by Telligent Systems