2009-09-11 6 views
42

Ich hatte heute das folgende Problem, und ich fragte mich, ob es eine Lösung für mein Problem gibt.Cast to Anonymous

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

, die bisher gut funktioniert.

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

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

Ich denke, es gibt keine Möglichkeit, den Typ von "Current" herausfinden und auf die Eigenschaft "Id" zugreifen? Vielleicht hat jemand eine gute Lösung ...

Ich weiß, es gibt andere (und auch bessere) Möglichkeiten, die ID (Reflection, Lesen des Wertes aus der ComboBox, nicht mit anonymen tpyes, ...) I ' Ich bin nur neugierig, wenn es möglich ist, den Typ aus bsOptions.Current auf elegante Weise zu bekommen.

+0

Br ... anonyme Klasse kann nützlich (manchmal), aber wirklich verwendet wird, auf diese Weise, für mich ist es eine Regression zu VB Alter ist: /. –

+1

Warten Sie, bis Dynamik in die Szene eintritt, seien Sie froh, dass wir nur Fragen zur Weitergabe anonymer Objekte sehen. –

+1

Richtig, mit viel Glück haben wir ein brandneues "Marquee" -Attribut auf dem Label: D –

Antwort

69

Hinweis, nach dem Kommentar, ich möchte nur darauf hinweisen möchte, dass ich auch empfehlen eine echte Art zu verwenden, wenn Sie es um das Programm wie folgt übergeben müssen. Anonyme Typen sollten eigentlich nur lokal in einer einzigen Methode verwendet werden (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, die gleichen anonymen Typ (gleiche Eigenschaften, gleiche Reihenfolge) wird in denselben Typ aufgelöst, wodurch der obige Trick funktioniert.

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

Nutzung:

var value = x.CastTo(a); 

Aber wir wirklich die Grenzen hier drücken. Benutze einen echten Typ, es sieht genauso aus und fühlt sich auch sauberer an.

+0

ich nicht Wie auch immer, da es fehleranfällig sein kann, ist es viel besser, nur eine tatsächliche Klasse zu erstellen, die die Werte enthält. –

+0

Ich stimme zu, obwohl es nicht wirklich fehleranfällig ist, aber ich stimme zu, eine echte Art ist hier gerechtfertigt, ich habe die Antwort bearbeitet, um klarzustellen. –

+4

Laut Mads Torgersen bezeichnet das C# -Team diesen Trick als "Cast by Example". Siehe seinen Kommentar (der erste) zu diesem Artikel: http://tomasp.net/blog/cannot-return-anonymous-type-from-method.aspx – LukeH

8

MSDN zu zitieren:

Ein anonymer Typ umgewandelt werden kann, nicht auf eine Schnittstelle oder Typen mit Ausnahme Objekt.

6

In C# 3.0 ist dies nicht möglich. Sie müssen auf C# 4.0 warten, das den Zugriff auf Eigenschaften zur Laufzeit mit "dynamischen" Variablen ermöglicht.

0

Sie auch eine Reihe von anonymen Typen direkt mit dieser Syntax deklarieren:

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

... .dann zum Umwandeln:

+1

aber die schönheit von anonymen wird hier verloren ... ich muss SomeClasses schreiben ... – gsharp

+0

@gsharp. Mein Anwendungsfall ist das Testen eines Jsonresult durch Unit, bei dem ein anonymer Typ mehrerer realer Klassen gesendet wird. Ich habe also schon SomeClasses, wollte aber einen anonymen Typ für die Weitergabe von json. Das funktioniert perfekt für mich, danke. –

15

Anstatt den benutzerdefinierten Typ zu verwenden, versuchen Sie es mit dem dynamischen Typ.

Ihre Event-Handler wie folgt aussehen würde:

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

+1 - Dies ist eine gute Option in C# 4.0. option.Id wird in diesem Fall zur Laufzeit ausgewertet. –

Verwandte Themen