2009-09-11 22 views
42

Tuve el siguiente problema hoy, y me preguntaba si hay una solución para mi problema.Transmitido a tipo anónimo

Mi idea era construir clases anónimas y utilizarlo como una fuente de datos para un WinForm BindingSource:

public void Init() 
{ 
    var option1 = new 
        { 
         Id = TemplateAction.Update, 
         Option = "Update the Templates", 
         Description = "Bla bla 1." 
        }; 

    var option2 = new 
        { 
         Id = TemplateAction.Download, 
         Option = "Download the Templates", 
         Description = "Bla bla 2." 
        }; 

    var list = new[] {option1, option2}.ToList(); 

    bsOptions.DataSource = list; // my BindingSource 

    // cboTemplates is a ComboBox 
    cboTemplates.DataSource = bsOptions; 
    cboTemplates.ValueMember = "Id"; 
    cboTemplates.DisplayMember = "Option"; 

    lblInfoTemplates.DataBindings.Add("Text", bsOptions, "Description"); 
} 

que funciona muy bien hasta ahora.

El problema que tuve es conseguir Id de la propiedad "actual" de la BindingSource, porque no puedo echarlo de nuevo al tipo anónimo:

private void cmdOK_Click(object sender, EventArgs e) 
{ 
    var option = (???)bsOptions.Current; 
} 

supongo que no hay manera de averiguar el tipo de "Actual" y acceder a la propiedad "Id"? Tal vez alguien tiene una buena solución ...

Sé que hay otros (y también mejor) maneras de obtener el Id (reflexión, la lectura del valor del desplegable, no usar tpyes anónimos, ...) I' Es muy curioso si es posible sacar el Tipo de bsOptions.Current de una manera elegante.

+0

Br ... clase anónima puede ser útil (a veces), pero en realidad, se utiliza de esa manera, para mí es una regresión a la edad de VB: /. –

+1

Simplemente espere hasta que la dinámica entre en escena, alégrese de que solo estamos viendo preguntas sobre cómo pasar objetos anónimos. –

+1

Correcto, con suficiente suerte, tendremos un nuevo atributo de "marquesina" en la etiqueta: D –

Respuesta

69

Nota, de acuerdo con el comentario, sólo quisiera señalar que yo también recomiendo el uso de un tipo de bienes cuando se necesita para pasarlo alrededor del programa como este. Los tipos anónimos solo deberían usarse localmente de una sola vez (en mi opinión), pero de todos modos, aquí está el resto de mi respuesta.


usted puede hacerlo utilizando un truco, engañando al compilador en inferir el tipo correcto para usted:

using System; 

namespace ConsoleApplication4 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      var a = new { Id = 1, Name = "Bob" }; 
      TestMethod(a); 

      Console.Out.WriteLine("Press enter to exit..."); 
      Console.In.ReadLine(); 
     } 

     private static void TestMethod(Object x) 
     { 
      // This is a dummy value, just to get 'a' to be of the right type 
      var a = new { Id = 0, Name = "" }; 
      a = Cast(a, x); 
      Console.Out.WriteLine(a.Id + ": " + a.Name); 
     } 

     private static T Cast<T>(T typeHolder, Object x) 
     { 
      // typeHolder above is just for compiler magic 
      // to infer the type to cast x to 
      return (T)x; 
     } 
    } 
} 

El truco es que el interior del conjunto, el mismo tipo anónimo (mismas propiedades, mismo orden) se resuelve con el mismo tipo, lo que hace que funcione el truco anterior.

private static T CastTo<T>(this Object value, T targetType) 
{ 
    // targetType above is just for compiler magic 
    // to infer the type to cast x to 
    return (T)x; 
} 

uso:

var value = x.CastTo(a); 

Pero realmente estamos empujando los límites aquí. Use un tipo real, se verá y se sentirá más limpio también.

+0

No lo hago así, ya que puede ser propenso a errores, mucho mejor simplemente crear una clase real para mantener los valores. –

+0

Acepto, aunque en realidad no es tan propenso a errores, pero estoy de acuerdo, un tipo real está garantizado aquí, edité la respuesta para aclarar. –

+4

Según Mads Torgersen, el equipo de C# se refiere a este truco como "emitir con el ejemplo". Ver su comentario (el primero) en este artículo: http://tomasp.net/blog/cannot-return-anonymous-type-from-method.aspx – LukeH

8

Para citar MSDN:

un tipo anónimo no se puede convertir a cualquier interfaz o escribe a excepción de objeto.

6

En C# 3.0, esto no es posible. Tendrá que esperar C# 4.0, que permite acceder a las propiedades en tiempo de ejecución utilizando variables "dinámicas".

0

También puede declarar una matriz de tipos anónimos directamente con la sintaxis:

var data = new [] { 
    new {Id = 0, Name = "Foo"}, 
    new {Id = 42, Name = "Bar"}, 
}; 
1
public class MyExtensMethods{ 

    public static T GetPropertyValue<T>(this Object obj, string property) 
    { 
     return (T)obj.GetType().GetProperty(property).GetValue(obj, null); 
    } 
} 

class SomeClass 
{ 
    public int ID{get;set;} 
    public int FullName{get;set;} 
} 


// casts obj to type SomeClass 
public SomeClass CastToSomeClass(object obj) 
{ 
    return new SomeClass() 
    { 
     ID = obj.GetPropertyValue<int>("Id"), 
     FullName = obj.GetPropertyValue<string>("LastName") + ", " + obj.GetPropertyValue<string>("FirstName") 
    }; 
} 

... .Luego, para emitir, lo hará:

var a = new { Id = 1, FirstName = "Bob", LastName="Nam" }; 
SomeClass myNewVar = CastToSomeClass(a); 
+1

pero la belleza del anónimo se pierde aquí ... tengo que escribir SomeClasses ... – gsharp

+0

@gsharp. Mi caso de uso es para la prueba unitaria de Jsonresult, que envía un tipo anónimo de múltiples clases realizadas. Así que ya tengo SomeClasses pero quería un tipo anónimo para pasar json. Esto funciona perfecto para mí, gracias. –

15

En lugar de convertir a su tipo personalizado intente utilizar el tipo dinámico.

Su controlador de eventos sería algo como esto:

private void cmdOK_Click(object sender, EventArgs e) 
{ 
    dynamic option = bsOptions.Current; 
    if (option.Id == 1) { doSomething(); } 
     else { doSomethingElse(); } 
} 
+2

+1 - Esta es una buena opción en C# 4.0. option.Id se evaluará en tiempo de ejecución en este caso. –

Cuestiones relacionadas