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.XM开发者_如何学GoLserializeLDAPconfig.DeserializeFromXML(Of XMLserialization.cConfiguration)()
Is there a way to call a generic function by getting the type from the instance ?
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)()
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
}
Only using the methods of the System.Reflection
namespace, which really isn't worth it for the effort you're trying to save.
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.
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.
[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.
精彩评论