Question

J'ai eu le problème suivant aujourd'hui et je me demandais s'il existe une solution à mon problème.

Mon idée était de créer des classes anonymes et de l'utiliser comme source de données pour 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");
}

Cela fonctionne très bien jusqu'à présent.

Le problème que j’ai eu à résoudre est d’obtenir l’identifiant hors du champ "Actuel". propriété de BindingSource, car je ne peux pas le remettre dans le type anonyme:

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

Je suppose qu’il n’ya aucun moyen de connaître le type de " Actuel " et accédez au " Id " Propriété? Peut-être que quelqu'un a une bonne solution ...

Je sais qu’il existe d’autres moyens (mais aussi de meilleurs) d’obtenir l’Id (réflexion, lecture de la valeur de la ComboBox, utilisation de mots anonymes, ...). Je suis simplement curieux s’il est possible de sortir le Type. de bsOptions.Current d’une manière élégante.

Était-ce utile?

La solution

Remarque , comme dans le commentaire, je voudrais juste souligner que moi aussi je recommande d'utiliser un type réel lorsque vous devez le faire circuler dans le programme, comme ce. Les types anonymes ne devraient vraiment être utilisés localement que dans une seule méthode à la fois (à mon avis), mais voici le reste de ma réponse.

Vous pouvez le faire en utilisant une astuce, en incitant le compilateur à déduire le bon type pour vous:

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

Le truc, c’est qu’à l’intérieur de l’assemblage, le même type anonyme (mêmes propriétés, même ordre) résout le même type, ce qui rend l’astuce précédente.

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

utilisation:

var value = x.CastTo(a);

Mais nous repoussons vraiment les limites ici. Utilisez un type réel, il aura l’air plus propre.

Autres conseils

Au lieu d'utiliser votre type personnalisé, essayez d'utiliser un type dynamique.

Votre gestionnaire d'événements devrait ressembler à ceci:

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

Pour citer MSDN :

  

Un type anonyme ne peut pas être converti en interface ni en type, à l'exception d'un objet.

En C # 3.0, cela n’est pas possible. Vous devrez attendre la version 4.0 de C #, qui permet d’accéder aux propriétés au moment de l’exécution à l’aide de " 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")
     };
}

.... alors pour faire un casting, vous ferez:

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

vous pouvez essayer ceci:

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

voir: Vous ne pouvez pas retourner le type anonyme de la méthode? Vraiment?

Vous pouvez également déclarer directement un tableau de types anonymes avec cette syntaxe:

var data = new [] {
  new {Id = 0, Name = "Foo"},
  new {Id = 42, Name = "Bar"},
};
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top