views:

86

answers:

2

I'm not sure how to describe this but I'm trying to create a base class that contains a shared (factory) function called FromXml. I want this function to instantiate an object of the proper type and then fill it via an XmlDocument.

For example, let's say I have something like this:

Public Class XmlObject
    Public Shared Function FromXml(ByVal source as XmlDocument) As XmlObject
        // <need code to create SPECIFIC TYPE of object and return it
    End Function
End Class

Public Class CustomObject
    Inherits XmlObject
End Class

I'd like to be able to do something like this:

Dim myObject As CustomObject = CustomObject.FromXml(source)

Is this possible?

A: 

If you want to tell a function to do something with a specific type, just add generic parameters to it. Not sure if this is the best way to go about your original intent, but it will get the job done.

   Public Class XmlObject
      Public Shared Function FromXml(Of T)(ByVal source As XmlDocument) As T
         Dim result As T = Activator.CreateInstance(GetType(T))

         Return result
      End Function
   End Class
hometoast
+1  A: 

First, the FromXml function must know the type of object it needs to create and return. To do that, you could either:

Pass the type itself as a parameter:

Public Shared Function FromXml(ByVal source As XmlDocument, _
                               ByVal resultType As Type) As XmlObject
End Function

Use Generics:

Public Shared Function FromXml(Of T)(ByVal source As XmlDocument) As XmlObject

End Function

(Using Generics, you can also specify, for example, "Of T as XmlObject", to only recieve in T a class assignable to XmlObject).

Next, you'll have to decide how to instantiate a new object of the passed type. You can either investigate the exact type passed and create a new instance accordingly (hard-coded), or use Reflection to invoke a constructor method of the passed type (assuming it has a an accessable constructor)(see example here). This may prove a bit tricky, because if T has no empty constructors then you'll have to investigate the constructors' arguments and invoke a matchin delegate (again, using Reflection).

M.A. Hanin
Nice. I actually didn't know you could restrict the generic parameter to a specific class. That would have saved me lots of silly "If TryCast..." code.
hometoast
It works well, you can restrict to interfaces, and make generic restrictions (Class SomeClass(of TBase)... Function myFunc(of T as TBase), etc. etc.I didn't know anything about Activator.CreateInstance, I'll check it out :-)
M.A. Hanin