VB.NET equivalente para C#''dynamic'' con Option Strict On
option-strict (7)
El equivalente es Object en VB.NET pero con Option Strict Off
. Con Option Strict On
no hay equivalente. Dicho de otra manera, la palabra clave dynamic trae la funcionalidad equivalente a la Option Strict Off
a C #.
¿Hay un equivalente para la palabra clave ''dynamic'' de C # 4 cuando se usa el tipo seguro VB.NET, es decir, con Option Strict On
?
Esto demostrará lo que Basic está diciendo acerca de que VB no tiene la misma granularidad que C #. Tengo este fragmento de código en C #, que usa la reflexión para invocar dinámicamente un método en tiempo de ejecución:
var listResult = tgtObj.GetType().GetMethod("GetSomeData").Invoke(tgtObj, null);
La razón por la que hago esto es porque "GetSomeData" podría ser cualquiera de una serie de métodos, cada uno obteniendo datos diferentes. ¿Qué método invocar aquí depende de un parámetro de cadena pasado a este objeto en tiempo de ejecución, entonces, el valor de "GetSomeData" varía en tiempo de ejecución.
La firma de "GetSomeData" es:
public List<SomeResultSetClass> GetSomeData()
Cada uno de los métodos invocados devuelve algún tipo de objeto List<T>
. A continuación, envío el objeto listResult a un método genérico llamado Export, que se ve así:
void Export<T>(List<T> exportList, string filePath, byte fileType) where T: class;
Aquí es donde nos encontramos con un problema. Invoke devuelve un objeto de tipo System.Object. Por supuesto, una List<T>
es también un Objeto del Sistema, pero la interfaz expuesta es la interfaz System.Object, no la interfaz IList. Si intento ejecutar el método Exportar, así:
myExportObj.Export(listResult, parms.filePath, parms.fileType);
el código no puede compilarse El error es:
The type arguments for method ''...Export<T>...'' cannot be inferred from the usage. Try specifying the type arguments explicitly.
¡¡No, gracias!! El problema es que el compilador no puede encontrar los metadatos IList, porque está mirando la interfaz System.Object. Ahora puede crear una nueva List<T>
, asignar (List<Whatever>) listResult
a ella, pero eso en primer lugar no (List<Whatever>) listResult
con el propósito de la invocación dinámica.
La solución es cambiar var
a dynamic
:
dynamic listResult = tgtObj.GetType().GetMethod("GetSomeData").Invoke(tgtObj, null);
Como Dynamic evita la comprobación del tipo estático en tiempo de compilación, no obtenemos un error de compilación. Luego, cuando el objeto dinámico pasa al método Export, el DLR (Dynamic Language Runtime) busca ver si puede convertir implícitamente el objeto para cumplir con los requisitos de la firma del método. Lo que por supuesto puede.
Ok, así es como funcionan las cosas en C #. Con VB, la línea es así:
Dim listResult = tgtObj.GetType().GetMethod("GetSomeData").Invoke(tgtObj, Nothing)
Con Option Strict On, esta línea altera el compilador, como se esperaba. Sin eso, funciona bien. En otras palabras, en VB, tengo que desactivar el comprobador de tipos para todo el módulo que contiene la línea. No hay una granularidad más fina que eso.
Existen suficientes formas de manejar métodos y propiedades con objetos COM de vinculación tardía y escribir safe ( Option Strict On
). Esto al usar los métodos Microsoft.VisualBasic.Interaction.CallByName y System.Type.InvokeMember. (O cree un archivo "parcial" separado donde Option Strict
está Off
).
Pero manejar eventos con enlace tardío de VB.NET no es tan sencillo como con el tipo dinámico en C #. Puede verificar el "truco" para eso en Eventos dinámicos en VB.NET .
Puede activar Option Infer y Option Strict Off y aún tener algo muy cercano.
Sí, ExpandoObject.
Dim DObj = Nuevo System.Dynamic.ExpandoObject ()
DObj.A = "abc"
DObj.B = 123
Tenga en cuenta que, incluso con Option Strict en, todavía puede usar, por ejemplo, un ExpandoObject para acceder a propiedades como:
Dim doc = JsonConvert.DeserializeObject(Of ExpandoObject)("{""name"":""Bob""}")
Dim lookup as IDictionary(Of String, Object) = doc
lookup("name") '' Bob
VB.NET siempre tenía incorporada la función "dinámica", originalmente llamada vinculación tardía. Esta sintaxis fue soportada para siempre:
Dim obj = new SomeComClass()
obj.DoSomething()
Trabajó en código implementado en .NET y COM, siendo este último el uso más común. La palabra clave dinámica en C # le dio esa misma capacidad. Sin embargo, cambió en la versión 10 de VB.NET, ahora también está usando el DLR. Lo cual agrega soporte para enlaces dinámicos a implementaciones de lenguaje como Python y Ruby.
La sintaxis es exactamente la misma, use la palabra clave Dim sin As. Sin embargo, tendrá que usar Option Strict Off, Option Infer On puede suavizar ese golpe un poco. Muestra que C # usando una palabra clave específica para señalar el enlace dinámico fue una jugada bastante buena. Afaik todas las solicitudes para hacerlo en VB.NET también han sido consideradas pero no planeadas.
Si prefiere Opción estricta activada entonces, usar la palabra clave Clase parcial para que pueda mover parte del código a otro archivo fuente es probablemente el enfoque más efectivo.