Frage

Ich hatte folgendes Problem heute, und ich frage mich, ob es eine Lösung für mein Problem ist.

Meine Idee war es, anonyme Klassen zu bauen und sie als Datenquelle für eine WinForm Binding verwenden:

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

Das funktioniert so weit in Ordnung.

Das Problem, das ich hatte, ist Id, um aus der „Current“ Eigenschaft des Binding, weil ich es nicht zurück in den Anonymous Typen werfen kann:

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

Ich denke, es gibt keine Möglichkeit, die Art von „Current“, um herauszufinden, und das „Id“ Eigentum zugreifen? Vielleicht hat jemand eine gute Lösung ...

Ich weiß, es gibt auch andere (und auch besser) Möglichkeiten, die Id (Spiegelung, den Wert aus der ComboBox zu lesen, nicht anonym tpyes verwenden, ...) zu erhalten, ich bin nur courious wenn es möglich ist, die Art raus von bsOptions.Current auf elegante Weise.

War es hilfreich?

Lösung

Hinweis , gemäß dem Kommentar, würde ich nur darauf hinweisen, dass ich auch empfehlen eine echte Art zu verwenden, wenn Sie es um das Programm zu übergeben müssen, wie diese. Anonyme Typen sollten zu einem Zeitpunkt werden nur wirklich verwendeten lokal in einem einzigen Verfahren (meiner Meinung nach), aber wie auch immer, hier ist der Rest meiner Antwort.


Sie können es einen Trick verwenden, durch den Compiler in trickst die richtige Art für Sie Folgern:

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

Der Trick besteht darin, dass in der Versammlung, der gleiche anonyme Typ (gleiche Eigenschaften gleiche Reihenfolge) löst auf den gleichen Typen, der den Trick über Arbeit macht.

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

Nutzung:

var value = x.CastTo(a);

Aber wir wirklich die Grenzen hier drücken. Verwenden Sie einen echten Typ, es wird aussehen und sich anfühlen sauberer als gut.

Andere Tipps

Statt zu Ihrer benutzerdefinierten Art von Casting versuchen dynamischen Typ verwendet wird.

Ihre Event-Handler in etwa so aussehen:

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

MSDN :

  

Ein anonymer Typ kann nicht an jede Schnittstelle oder Typen mit Ausnahme Objekt gegossen werden.

In C # 3.0 ist dies nicht möglich. Sie werden für C # 4.0 warten müssen, welche Eigenschaften zur Laufzeit ermöglicht den Zugriff auf „dynamische“ Variablen.

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

.... dann werfen Sie tun:

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

Sie können versuchen, diese:

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

siehe: Kann nicht anonymen Typen von Methode zurückgeben? Wirklich?

Sie können auch eine Reihe von anonymen Typen direkt mit dieser Syntax deklarieren

var data = new [] {
  new {Id = 0, Name = "Foo"},
  new {Id = 42, Name = "Bar"},
};
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top