it-swarm.com.de

Durchlaufen Sie die Eigenschaften und Werte eines Objekts, die über eine linq-Abfrage in einem Domänenmodell zurückgegeben werden

Ich habe eine benutzerdefinierte Entität in einer relationalen Datenbank, die ich über ein Domänenmodell der CLR zugeordnet habe. Wenn Sie die folgende Anweisung verwenden, kann ich eine Entität aus meiner Datenbank über eine LINQ-Abfrage im Domänenmodell in den Speicher ziehen.

var inspection = (from i in dbContext.New_testinspectionExtensionBases
              where i.New_testinspectionId == currentInspection   
              select i).First();                         

Es gibt Eigenschaften/Felder in dieser Entität, auf die ich zugreifen muss. Ich muss in der Lage sein, den Eigenschaften-/Feldnamen sowie dessen Wert zu ermitteln. Ich möchte diese Elemente im Speicher durchlaufen und deren Namen und Werte in die Konsole schreiben.

Ich habe versucht, diesen Ansatz zu verwenden, konnte aber nicht herausfinden, wie die Syntax korrigiert werden kann. Es spielt jedoch keine Rolle, da ich nur lesenden Zugriff auf den Wert habe.

var inspectionReportFields = inspection.GetType().GetProperties(); 
// I called this inspectionReportfields because the entity properties correspond to 
// form/report fields I'm generating from this data.

foreach (var reportField in inspectionReportFields)
{
    var value = reportField.GetValue();
    Console.WriteLine(reportField.Name);
    Console.WriteLine(value);
}

Gibt es eine einfachere Methode, um den Eigenschafts-/Feldwert zu erhalten, wenn ein Domänenmodell wie EF oder Openaccess verwendet wird? Wenn nicht, gehe ich den richtigen Weg? Und wenn ja, wie kann ich die Syntax in der Wertvariablendeklaration korrigieren?

Hier sind einige Beispielfelder/-eigenschaften aus dem vom Domänenmodell generierten Code als Referenz.

    private int? _new_systemGauges;
    public virtual int? New_systemGauges 
    { 
        get
        {
            return this._new_systemGauges;
        }
        set
        {
            this._new_systemGauges = value;
        }
    }

    private int? _new_systemAlarm ;
    public virtual int? New_systemAlarm 
    { 
        get
        {
            return this._new_systemAlarm;
        }
        set
        {
            this._new_systemAlarm = value;
        }
    }
37
bdemartino

Ich gehe davon aus, dass Sie versuchen, eine allgemeine Methode zum "Dumping" eines Objekts zu definieren, ohne etwas über seine Struktur zu wissen. Wenn ja, dann gehen Sie den richtigen Weg. Sie verwenden Reflection (GetType() und die zugehörigen Klassenmethoden Type), um das Objekt zu untersuchen und seine Informationen zurückzugeben.

Der Grund, warum GetFields() nichts zurückgegeben hat, ist, dass Sie wahrscheinlich nicht die richtigen Bindungsflags angegeben haben. Wenn Sie die Überladung aufrufen, für die keine Parameter erforderlich sind, erhalten Sie nur public-Felder zurück. Wenn Sie private Felder wünschen, müssen Sie sie speziell anfragen.

In Ihrem Fall würde GetFields(BindingFlags.NonPublic) Ihnen die Felder _new_systemGauges und _new_systemAlarm zurückgeben, während GetProperties () die Eigenschaften New_systemAlarm und New_systemAlarm zurückgibt.

Das andere wichtige Element, das Sie übersehen haben, ist, dass die Daten, die Sie zurückerhalten, die Metadaten type sind; Es definiert die Struktur der class und keine bestimmte Instanz. Wenn Sie wissen möchten, welchen Wert eine Eigenschaft für eine bestimmte Instanz hat, müssen Sie danach fragen:

foreach (var prop in obj.GetType().GetProperties())
{
  Console.WriteLine("{0} = {1}", prop.Name, prop.GetValue(obj, null));
}

Wenn Sie eines der PropertyInfo-Elemente aus den Metadaten des Typs haben, können Sie den Wert dieser Eigenschaft für jede Instanz dieses Typs anfordern. Es muss nicht dieselbe Instanz sein, die Sie ursprünglich verwendet haben. Zum Beispiel:

var objs = somelist.Where(x => x.Id == 1);
foreach (var prop in objs.First().GetType().GetProperties())
{
  int x = 0;
  foreach (var obj in objs)
  {        
    if (prop.PropertyType.Name.Equals("Int32"))
    {
      int val = (int)prop.GetValue(obj, null);
      Console.WriteLine("Obj #{0}: {1} = 0x{2:x8}", x++, prop.Name, val);
    }
    else if (prop.PropertyType.Name.Equals("Decimal"))
    {
      int val = (decimal)prop.GetValue(obj, null);
      Console.WriteLine("Obj #{0}: {1} = {2:c2}", x++, prop.Name, val);
    }
    else
    {
      Console.WriteLine("Obj #{0}: {1} = '{2}'", x++, prop.Name, prop.GetValue(obj, null));
    }
  }
}

Technisch sollten Sie das Ergebnis von GetIndexParameters überprüfen, um festzustellen, ob eine Eigenschaft indiziert ist oder nicht. Der null-Parameter für GetValue ist tatsächlich ein Array von Indexwerten.

Um den zurückgegebenen Wert zu konvertieren, können Sie entweder Typumwandlungen verwenden. Wenn Sie jedoch etwas flexibler sein möchten, verwenden Sie die Methoden der Convert-Klasse. Der Unterschied ist zum Beispiel, wenn Sie eine short -Eigenschaft haben, gibt GetValue() eine Box-Short zurück, die Sie dann nicht als int eingeben können. Sie müssen es zuerst auf eine short entpacken. Mit Convert.ToInt32() werden alle erforderlichen Schritte ausgeführt, um aus einer beliebigen Eigenschaft, die convertible in eine ganze Zahl ist, einen int-Wert zu erhalten.

Das Konvertieren zwischen Referenztypen ist einfacher, da Sie einfach is und as verwenden können. Diese arbeiten genau so, wie Sie es von "reflektierten" Eigenschaftswerten erwarten würden.

73

GetProperties ist in der Tat die richtige Methode.

Um den Compiler-Fehler zu beseitigen, ändern Sie Ihren Code wie folgt:

var value = reportField.GetValue(inspection, null);

Sie müssen die Instanz übergeben, von der Sie den Wert erhalten möchten, da ein PropertyInfo-Objekt nicht an eine bestimmte Klasseninstanz gebunden ist.


Beachten Sie bitte die Standard-Benennungsregeln von .NET.

Dies würde zu folgendem führen:

NewSystemAlarm statt New_systemAlarm
newSystemAlarm oder _newSystemAlarm statt _new_systemAlarm
NewTestInspectionExtensionBases anstelle von New_testinspectionExtensionBases
NewTestInspectionId anstelle von New_testinspectionId

2
Daniel Hilgarth

Wenn Sie OpenAccess verwenden, stehen Ihnen stets die vollständigen Informationen zu Ihren Modellklassen zur Verfügung. Die Informationen werden aus Ihrem Mapping abgerufen. Dies bedeutet, dass Sie nicht über Ihre Klassen nachdenken müssen (kein Overhead).

Stöbern Sie einfach durch context.Metadata.PersistentTypes nach all Ihren Klassenzuordnungsinformationen. 

0
sovanesyan