Reputation: 82186
Question: I want to call a generic function, defined as:
Public Shared Function DeserializeFromXML(Of T)(Optional ByRef strFileNameAndPath As String = Nothing) As T
Now when I call it, I wanted to do it with any of the variants below:
Dim x As New XMLserialization.cConfiguration
x = XMLserialization.XMLserializeLDAPconfig.DeserializeFromXML(Of x)()
x = XMLserialization.XMLserializeLDAPconfig.DeserializeFromXML(GetType(x))()
x = XMLserialization.XMLserializeLDAPconfig.DeserializeFromXML(Of GetType(x))()
But it doesn't work. I find it very annoying and unreadable having to type
x = XMLserialization.XMLserializeLDAPconfig.DeserializeFromXML(Of XMLserialization.cConfiguration)()
Is there a way to call a generic function by getting the type from the instance ?
Upvotes: 6
Views: 5330
Reputation: 128327
It sounds to me like you want to create a shorter alias for your XMLserialization.cConfiguration
type. Try using the Imports
statement to accomplish this:
' at the top of the file
Imports C = XMLserialization.cConfiguration
' somewhere in the body of the file
Dim x = XMLserialization.XMLserializeLDAPconfig.DeserializeFromXML(Of C)()
Upvotes: 4
Reputation: 155662
There's a good reason why you can't do this easily in code and why the reflection is so much extra work: generics are all about preserving type, so you can have a List(Of Integer)
instead of a List(Of Object)
and have to cast/box everything, and they improve code-maintainability by maintaining strong typing through the code (so you get fewer run-time cast and type exceptions).
Generics are really compile-time. They let you defer the type being specified so that your generic code can be re-used or have the type specified by another assembly.
However your deserialisation is run time - you don't know what type you'll have when you're writing the code, which is why you need a variable to hold the type. In this case there isn't really any benefit to having the generic code - your serialisation costs will be orders of magnitude greater than the boxing cost, and there's no code-maintainability benefit for the strongly typed result as you still don't know what it is at compile-time.
In short, this being hard is .Net's way of telling you to review your initial assumptions - change your method to:
Public Shared Function DeserializeFromXML(Optional ByRef strFileNameAndPath As String = Nothing) As Object
And then cast your result from object to your XMLserialization.cConfiguration
class.
Upvotes: 1
Reputation: 10931
[This is answering the question as asked, not necessarily solving your bigger issue.]
To avoid the Of cConfiguration
being required you could include an ignored ByVal Configuration As T
in the generic method.
Then you could say
x = DeserializeFromXML(x)
But @DanTao's answer is probably better than mine unless you find a use for the Configuration
parameter.
Upvotes: 0
Reputation: 1062770
Generics and reflection make very poor friends. However, you can do this via MakeGenericMethod. However, that is going to be hard and ugly.
Since XmlSerializer
is based around Type
instance - I would reverse things: have the realy code Type
based, and call into that from the shallow generic version; example in C#:
public T DeserializeFromXML<T>(string path) {
return (T)DeserializeFromXML(typeof(T), path);
}
public object DeserializeFromXML(Type type, string path) {
//TODO: real code
}
Upvotes: 4
Reputation: 19308
The type of a generic method is determined at compile time, which is why you can't set it using a variable. This is a key difference between generic programming and type reflection.
Upvotes: 1
Reputation: 72860
Only using the methods of the System.Reflection
namespace, which really isn't worth it for the effort you're trying to save.
Upvotes: 2