Pregunta

Tuve el siguiente problema hoy, y me preguntaba si hay una solución para mi problema.

Mi idea fue crear clases anónimas y usarlas como 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");
}

Eso funciona bien hasta ahora.

El problema que tuve es que el ID fuera del " Actual " propiedad de BindingSource, porque no puedo devolverlo al Tipo Anónimo:

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

Supongo que no hay forma de averiguar el tipo de " Actual " y accede a la " Id " ¿Propiedad? Quizás alguien tenga una buena solución ...

Sé que hay otras formas (y también mejores) de obtener la Id. (Reflexión, leyendo el valor de ComboBox, sin usar tpyes anónimos, ...) Solo soy cortés si es posible obtener el Tipo de bsOptions.Current de una manera elegante.

¿Fue útil?

Solución

Nota , según el comentario, me gustaría señalar que yo también recomiendo usar un tipo real cuando necesite pasarlo por el programa como esta. Los tipos anónimos solo deberían usarse localmente en un solo método a la vez (en mi opinión), pero de todos modos, aquí está el resto de mi respuesta.


Puedes hacerlo usando un truco, engañando al compilador para que infiera el tipo correcto para ti:

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 dentro del ensamblaje, el mismo tipo anónimo (las mismas propiedades, la misma orden) se resuelve en el mismo tipo, lo que hace que el truco anterior funcione.

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

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.

Otros consejos

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

Su controlador de eventos se vería así:

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

Para citar MSDN :

  

Un tipo anónimo no se puede convertir a ninguna interfaz o tipo, excepto para el objeto.

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

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")
     };
}

.... entonces para lanzar harás:

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

puedes probar esto:

private void cmdOK_Click(object sender, EventArgs e)
{
    var option = Cast(bsOptions.Current, new { Id = 0, Option = "", Description = "" });
}

vea: ¿No puede devolver el tipo anónimo desde el método? ¿En serio?

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

var data = new [] {
  new {Id = 0, Name = "Foo"},
  new {Id = 42, Name = "Bar"},
};
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top