2009-05-17 3 views
20

Ich habe ein Datagrid von einer Linq-Abfrage gefüllt. Wenn sich die fokussierte Zeile im Datagrid ändert, muss ich eine Variable festlegen, die einer der Eigenschaften in diesem Objekt entspricht.Wie kann ich einen Wert einer Eigenschaft von einem anonymen Typ erhalten?

Ich habe versucht ...

var selectedObject = view.GetRow(rowHandle); 
_selectedId = selectedObject.Id; 

... aber der Compiler überhaupt für diese ist es egal („Embedded-Anweisung kann keine Erklärung oder labled Aussage sein“).

Es scheint, als ob die Eigenschaft leicht zugänglich sein sollte. Wenn ich das Objekt zur Laufzeit überprüfe, werden alle Eigenschaften angezeigt, die ich erwarte. Ich weiß einfach nicht, wie ich darauf zugreifen soll.

Wie kann ich auf die Eigenschaft des anonymen Objekts zugreifen?

Edit für Klärungen:

ich zufällig sein mit DevExpress XtraGrid Kontrolle. Ich habe dieses Steuerelement mit einer Linq-Abfrage geladen, die aus mehreren verschiedenen Objekten besteht, so dass die Daten nicht wirklich mit irgendeiner Klasse übereinstimmen, die ich bereits habe (dh ich kann dies nicht auf irgendetwas anwenden).

Ich benutze .NET 3.5.

Wenn ich die Ergebnisse der view.GetRow (rowHandle) Methode sehen bekomme ich einen anonymen Typ, der wie folgt aussieht:

{ ClientId = 7, ClientName = "ACME Inc.", Jobs = 5 } 

Mein Ziel ist es, die ClientId von diesem anonymen Typ zu erhalten, so kann ich tun andere Dinge (wie zum Beispiel ein Formular mit diesem Client-Datensatz laden).

Ich habe ein paar der Vorschläge in den ersten Antworten versucht, konnte aber nicht an einen Punkt gelangen, an dem ich diese ClientId bekommen konnte.

+0

Was ist der genaue Typ der Kennung "view"? – AnthonyWJones

+0

"Ansicht" ist ein GridView-Steuerelement von DevExpress. –

Antwort

43

Haben Sie jemals versucht, Reflexion zu verwenden? Hier ist ein Beispiel-Code-Snippet:

// use reflection to retrieve the values of the following anonymous type 
var obj = new { ClientId = 7, ClientName = "ACME Inc.", Jobs = 5 }; 
System.Type type = obj.GetType(); 
int clientid = (int)type.GetProperty("ClientId").GetValue(obj, null); 
string clientname = (string)type.GetProperty("ClientName").GetValue(obj, null); 

// use the retrieved values for whatever you want... 
+0

Danke abdoul, dein Code ist ziemlich einfach zu verstehen. Ich hatte vor kurzem ein Problem, anonymen Typ und hier: http: //stackoverflow.com/questions/3534969/only-parameterless-constructors-and-initializers-are-supported-in-linq-to-entitie Ich habe die Frage. Nach einigem Suchen und Arbeiten am Wochenende bin ich auf diese Seite gekommen und es hat mir wirklich den Tag versüßt. – Developer

+0

Genau deshalb liebe ich SO – Bergkamp

+0

Wirklich, auch super Antwort! Dies ist, was ich seit 2 Wochen gesucht habe! Vielen Dank! – KomalJariwala

17

Eines der Probleme mit anonymen Typen ist, dass es schwierig ist, sie zwischen Funktionen zu verwenden. Es gibt keine Möglichkeit, einen anonymen Typ zu "benennen", und daher ist es sehr schwierig, zwischen ihnen zu wechseln. Dies verhindert, dass sie als Typausdruck für alles verwendet werden, was in Metadaten erscheint und vom Benutzer definiert wird.

Ich kann nicht genau sagen, welche API Sie oben verwenden. Es ist jedoch nicht möglich, dass die API einen stark typisierten anonymen Typ zurückgibt, sodass meine Schätzung in diesem selectedObject als Objekt eingegeben wird. C# 3.0 und darunter unterstützt keinen dynamischen Zugriff, sodass Sie nicht auf die Eigenschaften-ID zugreifen können, auch wenn sie zur Laufzeit verfügbar ist.

Sie werden nach einem der müssen die folgenden, um dieses

  • Verwenden Reflexion erhalten die Eigenschaft
  • einen vollständigen Typ erstellen zu greifen und dass das Datagrid
  • Verwenden Sie eine der vielen zu füllen verwenden hacky anonymen Typ wirft

EDIT

Hier ist ein Beispiel, wie ein Hack anonymen Typ zu tun, werfen

public T AnonymousTypeCast<T>(object anonymous, T typeExpression) { 
    return (T)anonymous; 
} 

... 
object obj = GetSomeAnonymousType(); 
var at = AnonymousTypeCast(obj, new { Name = String.Empty, Id = 0 }); 

Der Grund ist es Hacky ist, dass es sehr einfach ist, diese zu brechen. Zum Beispiel in der Methode, in der der anonyme Typ ursprünglich erstellt wird. Wenn ich dem Typ dort eine andere Eigenschaft hinzufüge, kompiliert der obige Code, aber scheitert zur Laufzeit.

+0

"Hacky anonyme Art wirft" was sind das? – AnthonyWJones

+0

@AnthonyWJones, ich habe ein Beispiel für einen anonymen Hacky-Typ hinzugefügt – JaredPar

+0

Vielen Dank für diese Antwort. Eine sehr schöne und elegante Lösung. Es hat nur einen Nachteil: Es funktioniert nicht, wenn das anonyme Objekt von einer anderen Assembly stammt. Dies ist ein Grund, warum Sie nie ein anonymes Objekt von einer Methode zurückgeben sollten, aber nicht jeder weiß das und deshalb muss ich mich mit einer Bibliothek beschäftigen, die genau das tut. –

0

Dies ist möglicherweise falsch (Sie haben möglicherweise nicht genügend Code dort), aber müssen Sie nicht in die Zeile indizieren, so dass Sie wählen, welche Spalte Sie möchten? Oder wenn „Id“ ist die Spalte, die Sie wollen, sollten Sie so etwas wie dies tun:

var selectedObject = view.GetRow(rowHandle); 
_selectedId = selectedObject["Id"]; 

Dies ist, wie ich den Inhalt einer Spalte in einem Datagrid greifen würde. Nun, wenn die Spalte selbst ein anonymer Typ ist, dann weiß ich nicht, aber wenn Sie nur eine benannte Spalte mit einem primitiven Typ bekommen, dann sollte das funktionieren.

1

Wie JaredPar richtig erraten hat, ist der Rückgabetyp GetRow()object. Wenn es mit dem DevExpress Grid arbeiten, können Sie den gewünschten Wert wie folgt extrahieren:

int clientId = (int)gridView.GetRowCellValue(rowHandle, "ClientId"); 

Dieser Ansatz hat ähnliche Nachteile wie die beschriebene „hacky anonymen Typ Cylinder“ vor: Sie haben einen magischen String benötigen eine die Spalte zur Identifizierung und Typ von Objekt in Int eingeben.

2

Als ich daran arbeitete, anonyme Typen herumzugeben und zu versuchen, sie neu zu schreiben, fand ich es letztendlich einfacher, einen Wrapper zu schreiben, der die Arbeit mit dem Objekt behandelte. Hier ist ein Link zu einem Blogeintrag darüber.

http://somewebguy.wordpress.com/2009/05/29/anonymous-types-round-two/

Letztlich würde der Code wie folgt aussehen.

//create an anonymous type 
var something = new { 
    name = "Mark", 
    age = 50 
}; 
AnonymousType type = new AnonymousType(something); 

//then access values by their property name and type 
type.With((string name, int age) => { 
    Console.Write("{0} :: {1}", name, age); 
}); 

//or just single values 
int value = type.Get<int>("age"); 
0

hoffte, das hilft, ist in einer Schnittstelle Liste vorbei, was ich brauche aus eine deutlichen Liste zu bekommen. Zuerst erhalte ich eine Liste mit anonymen Typen, und dann begehe ich sie, um sie in meine Objektliste zu übertragen.

private List<StockSymbolResult> GetDistinctSymbolList(List<ICommonFields> l) 
      { 
       var DistinctList = (
         from a 
         in l 
         orderby a.Symbol 
         select new 
         { 
          a.Symbol, 
          a.StockID 
         }).Distinct(); 

       StockSymbolResult ssr; 
       List<StockSymbolResult> rl = new List<StockSymbolResult>(); 
       foreach (var i in DistinctList) 
       { 
           // Symbol is a string and StockID is an int. 
        ssr = new StockSymbolResult(i.Symbol, i.StockID); 
        rl.Add(ssr); 
       } 

       return rl; 
      } 
17

Eine generische Lösung

public static T GetValueFromAnonymousType<T>(object dataitem, string itemkey) { 
    System.Type type = dataitem.GetType(); 
    T itemvalue = (T)type.GetProperty(itemkey).GetValue(dataitem, null); 
    return itemvalue; 
} 

Beispiel den Wert eines Datenelements für einen Schlüssel gegeben für immer:

var dataitem = /* Some value here */; 
bool ismember = TypeUtils.GetValueFromAnonymousType<bool>(dataitem, "IsMember"); 
+0

Ich fand diese Lösung die nächstbeste, um die anonymen Typen zu deklarieren. Vielen Dank. – DoomerDGR8

0

Sie können Schleife wie dies durch die Eigenschaften eines anonymen Typs :

var obj = new {someValue = "hello", otherValue = "world"}; 
foreach (var propertyInfo in obj.GetType().GetProperties() { 
    var name = propertyInfo.Name; 
    var value = propertyInfo.GetValue(obj, index: null); 
    ... 
} 
0

DevExpre ssxtraGridView hat eine Methode wie GetRowCellDisplayText (int rowHandle, GridColumn-Spalte). Mit dieser Methode gibt der folgende Code die ID aus dem anonymen Typ zurück.

var _selectedId = view.GetRowCellDisplayText(rowHandle, "Id"); 

Obwohl dies nicht eine Antwort auf die Frage abgibt „Wie ich Zugriff auf das anonyme Objekt Eigentum erhalten kann?“, Versucht es immer noch die Ursache des Problems zu lösen.

Ich habe dies mit devXpress Version 11.1 versucht und ich kann sehen, dass die Frage vor fast 2,5 Jahren zuerst gestellt wurde. Möglicherweise hat der Autor der Frage einen Workaround gefunden oder die Lösung selbst gefunden. Trotzdem antworte ich noch, damit es jemandem helfen kann.

11

Mit dem dynamischen Typ können Sie zur Laufzeit auf Eigenschaften anonymer Typen zugreifen, ohne die Reflektion zu verwenden.

var aType = new { id = 1, name = "Hello World!" }; 
//... 
//... 
dynamic x = aType; 
Console.WriteLine(x.name); // Produces: Hello World! 

mehr über dynamische Typ Lesen Sie hier: http://msdn.microsoft.com/en-us/library/dd264736.aspx

+0

So einfach und elegant Ich schäme mich, nicht daran zu denken :) – percebus

0

Wenn Sie wissen, was Sie tun und haben keine Angst, Laufzeitfehler zu bekommen, wenn Sie Ihre Änderungen am Code, können Sie Ihre Zeilendaten als dynamic werfen könnte:

var data = view.GetRow(rowHandle) as dynamic; 

int clientId  = data.ClientID; 
string clientName = data.ClientName; 
int jobs   = data.Jobs 

Keine Überprüfung der Kompilierzeit. Aber es sollte gut funktionieren.

0
var result = ((dynamic)DataGridView.Rows[rowNum].DataBoundItem).value; 
+0

Dies ist die einfachste Fomra, um den Wert der Attribute einer Liste zu erhalten (DataGridView) –

Verwandte Themen