Pasando tipo anónimo como parámetros del método

En la architecture de mi complemento actualmente estoy pasando un nombre de complemento (cadena), nombre de método (cadena) y parámetros (matriz de objetos) a mi servicio de complemento para ejecutar el método especificado y devolver el resultado (de tipo T).

El método de ejecución del servicio plugin se puede ver a continuación:

public TResult Execute(string pluginName, string operation, params object[] input) { MethodInfo method = null; TResult result = default(TResult); var plugin = _plugins.Enabled().FirstOrDefault(x => x.GetType().Name.Equals(pluginName, StringComparison.InvariantCultureIgnoreCase)); if (plugin != null) { method = plugin.GetType().GetMethods().FirstOrDefault(x => x.Name == operation); if (method != null) { result = (TResult)method.Invoke(plugin, input); } } return result; } 

Un ejemplo de uso:

 var url = AppHelper.PluginService.Execute( "ImagePlugin", "GetImageUrl", new object[] { image, size }); 

Lo que preferiría hacer es pasar un tipo anónimo en su lugar (ya que creo que esto es más legible), es decir,

 var url = AppHelper.PluginService.Execute( "ImagePlugin", "GetImageUrl", new { image = image, targetSize = size }); 

¿Cómo cambiaría mi método de Ejecución para asignar las propiedades de tipo anónimo a los parámetros de mi método de complemento?

Había considerado usar el nuevo tipo dynamic en .net 4.0, pero prefiero definir mis parámetros en el método del complemento en lugar de aceptar un objeto dynamic.

Gracias ben

[Actualizar]

Después de mirar a través del código fuente de ASP.NET MVC, parece lo suficientemente simple como para colocar el tipo anónimo en un diccionario de objetos, por ejemplo, RouteValueDictionary. Con la ayuda de la reflexión se crea dinámicamente una expresión linq. Aunque es una buena implementación, realmente no quería toda esta complejidad adicional.

Según el comentario a continuación, puedo lograr la legibilidad simplemente especificando mis parámetros en línea (sin necesidad de la statement de matriz de objetos):

 var url = AppHelper.PluginService.Execute("ImagePlugin", "GetImageUrl", image, size); 

Hay algunas maneras de hacer esto posible aunque no aconsejaría a ninguno de ellos.

Primero, puede utilizar la reflexión, lo que significa que tiene que escribir muchos códigos adicionales (propensos a errores) en su método PluginService.Execute para obtener los valores que desea.

Segundo, si conoce los parámetros del tipo anónimo que está pasando a su método, puede usar la técnica que se describe aquí . Puede convertir a otro tipo anónimo dentro de su método que tenga las mismas propiedades. Aquí hay otra descripción de la misma técnica de Jon Skeet.

En tercer lugar, puede usar clases de System.ComponentModel . Por ejemplo, ASP.NET MVC usa esto. Utiliza la reflexión bajo el capó. Sin embargo, en ASP.NET MVC, los nombres de propiedades son bien conocidos ( controller y action por ejemplo) o sus nombres no importan porque se pasan tal cual a un método de controlador ( id por ejemplo).

Finalmente encontré esta publicación que demuestra el uso de tipos anónimos como diccionarios. Usando este método, puede pasar el tipo anónimo como parámetro de método (objeto) y acceder a sus propiedades.

Sin embargo, también agregaría que después de ver las nuevas características dinámicas en .net 4.0, como ExpandoObject, se siente mucho más limpio pasar un objeto dynamic como parámetro:

  dynamic myobj = new ExpandoObject(); myobj.FirstName = "John"; myobj.LastName = "Smith"; SayHello(myobj); ........... public static void SayHello(dynamic properties) { Console.WriteLine(properties.FirstName + " " + properties.LastName); } 

Utilice el objeto dynamic para los parámetros si desea pasar un tipo anónimo. El método de ejecución de un complemento debe esperar ciertas propiedades de un objeto de parámetro para que funcione. Al utilizar la palabra clave dinámica, se le indicará al comstackdor C # que no realice una verificación de tipo en un parámetro y le permitirá usar una syntax fuertemente tipada en el código del complemento. La resolución del nombre de las propiedades se realizará en tiempo de ejecución y, si un objeto pasado no tuviera tales propiedades, se lanzará una excepción.

 var o = new { FirstName = "John", LastName = "Doe" }; var result = MyMethod(o); string MyMethod(dynamic o) { return o.FirstName + " " + o.LastName; } 

Lee más en esta entrada de blog

Este ejemplo convierte un objeto anónimo a un diccionario:

 IDictionary AnonymousObjectToDictionary(object propertyBag) { var result = new Dictionary(); if (propertyBag != null) { foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(propertyBag)) { result.Add(property.Name, property.GetValue(propertyBag)); } } return result; } 

Puedes llamarlo así:

 AnonymousObjectToDictionary(new { foo = 11, bar = "Be happy" }); 

Si se trata de un tipo anónimo de Linq, puede hacerlo fácilmente pasando IEnumerable.

Aquí hay un ejemplo de un método de recepción

  public static void MyMethod(ref IEnumerable ienum) { using (DataTable dt = new DataTable()) { ienum.First(ie => true).GetType().GetProperties().ToList().ForEach(pr => dt.Columns.Add(pr.Name, typeof(string))); //Parallelization not possible since DataTable columns must be in certain order ienum.ToList().ForEach(ie => //Parallelization not possible since DataTable rows not synchronized. { List objAdd = new List(); ie.GetType().GetProperties().ToList().ForEach(pr => objAdd.Add(ie.GetType().InvokeMember(pr.Name, BindingFlags.GetProperty, null, ie, null))); //Parallelization not possible since DataTable columns must be in certain order dt.Rows.Add(objAdd.ToArray()); objAdd.Clear(); objAdd = null; }); //Do something fun with dt } } 

Por supuesto, ya que estás utilizando la reflexión, es posible que veas problemas de rendimiento en machiens más lentos o donde tienes un IEnumerable grande o muchas propiedades en T.

Hola, he escrito un post al respecto:

http://blog.jorgef.net/2011/06/converting-any-object-to-dynamic.html

Espero que eso ayude.

Hice esto una vez. Lo que puede hacer es obtener los parámetros esperados de la función a través de la reflexión. Luego, puede construir su matriz de parámetros haciendo coincidir los nombres en la matriz de parámetros con las claves del objeto anónimo.

Espero que ayude :-).

 public static void ExAnonymousType() { var nguoi = new { Ten = "Vinh", Tuoi = 20 }; Console.WriteLine(nguoi.Ten + " " + nguoi.Tuoi); DoSomeThing(nguoi); } private static void DoSomeThing(object nguoi) { Console.WriteLine(nguoi.GetType().GetProperty("Ten").GetValue(nguoi,null)); } 

En primer lugar, verifique el espacio de nombres System.Addin, puede obtener ayuda allí.

En segundo lugar, puede crear su propia interfaz con el nombre y los parámetros específicos del método, y dejar que el complemento implemente la interfaz. Puede definir la interfaz del complemento en un proyecto diferente al que se puede hacer referencia tanto en la aplicación como en el proyecto del complemento.