2010-06-02 16 views
5

Pregunta: Quiero llamar a una función genérica, definida como:Llamar a una función genérica en VB.NET/C#

 Public Shared Function DeserializeFromXML(Of T)(Optional ByRef strFileNameAndPath As String = Nothing) As T 

Ahora, cuando la llamo, quería hacerlo con cualquiera de las variantes siguientes :

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))() 

Pero no funciona. me resulta muy molesto e ilegible tener que escribir

x = XMLserialization.XMLserializeLDAPconfig.DeserializeFromXML(Of XMLserialization.cConfiguration)() 

¿Hay una manera de llamar a una función genérica por conseguir el tipo de la instancia?

Respuesta

2

Solo usando los métodos del espacio de nombre System.Reflection, que realmente no vale la pena por el esfuerzo que está intentando guardar.

1

El tipo de método genérico se determina en tiempo de compilación, por lo que no puede establecerlo utilizando una variable. Esta es una diferencia clave entre la programación genérica y la reflexión de tipo.

3

Los genéricos y la reflexión hacen muy malos amigos. Sin embargo, usted puede hacerlo a través de MakeGenericMethod. Sin embargo, eso va a ser duro y feo.

Desde XmlSerializer se basa en Type ejemplo - Me revertir las cosas: tener el código realmenteType basa, y poner en que a partir de la versión genérica de poca profundidad; ejemplo en C#:

public T DeserializeFromXML<T>(string path) { 
    return (T)DeserializeFromXML(typeof(T), path); 
} 
public object DeserializeFromXML(Type type, string path) { 
    //TODO: real code 
} 
2

Me suena como si desea crear un alias más corto para su tipo XMLserialization.cConfiguration. Trate de usar la declaración Imports de lograr esto: [. Esto responde a la pregunta de por pedido, no necesariamente la solución de su problema más grande]

' at the top of the file 
Imports C = XMLserialization.cConfiguration 

' somewhere in the body of the file 
Dim x = XMLserialization.XMLserializeLDAPconfig.DeserializeFromXML(Of C)() 
0

Para evitar la Of cConfiguration que se requiera que podría incluir un ignorado ByVal Configuration As T en el método genérico.

Entonces se podría decir

x = DeserializeFromXML(x) 

Pero la respuesta de @ DanTao es probablemente mejor que la mía a menos que encontrar un uso para el parámetro Configuration.

1

Hay una buena razón por la cual no se puede hacer esto fácilmente en el código y por qué la reflexión es mucho trabajo extra: los genéricos son todos acerca de la preservación de tipo, por lo que puede tener un List(Of Integer) en lugar de un List(Of Object) y tienen que emitir/encerrar todo, y mejoran la mantenibilidad del código al mantener un tipeo fuerte a través del código (para que obtenga menos lanzamientos en tiempo de ejecución y escriba excepciones).

Los genéricos son realmente de tiempo de compilación. Le permiten diferir el tipo que se especifica para que su código genérico pueda reutilizarse o tener el tipo especificado por otro ensamblado.

Sin embargo, su deserialización es tiempo de ejecución; no sabe qué tipo tendrá cuando escriba el código, por lo que necesita una variable para contener el tipo.En este caso, no hay ningún beneficio para tener el código genérico: sus costos de serialización serán órdenes de magnitud mayores que el costo del boxeo, y no hay beneficio de mantenimiento del código para el resultado fuertemente tipado ya que aún no sabe qué está en tiempo de compilación.

En resumen, siendo este disco es manera de decirle a revisar sus hipótesis iniciales de .Net - cambiar su método para:

Public Shared Function DeserializeFromXML(Optional ByRef strFileNameAndPath As String = Nothing) As Object 

Y luego arrojado el resultado de un objeto a la clase XMLserialization.cConfiguration.

Cuestiones relacionadas