44

ドメインモデルを介してCLRにマップしたリレーショナルデータベースにカスタムエンティティがあります。したがって、次のステートメントを使用することで、ドメインモデルのLINQクエリを介して、データベースからメモリにエンティティをプルできます。

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

このエンティティにはアクセスする必要のあるプロパティ/フィールドがあります。プロパティ/フィールド名とその値を判別できる必要があります。これらのアイテムをメモリ内でループして、それらの名前と値をコンソールに書き出したいと思います。

このアプローチを使用してみましたが、構文を修正する方法がわかりませんでした(GetPropertiesが正しい使用方法であるかどうかもわかりません。また、GetFieldsは何らかの理由で何も返さなかったため、これが正しい方法だと思いました)しかし、必要なのは値への読み取りアクセスだけなので、実際には問題ではありません。

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

EFやopenaccessなどのドメインモデルを利用するときにプロパティ/フィールド値を取得する簡単な方法はありますか?そうでない場合、私はそれを正しい方法で行っていますか?そして最後に、もしそうなら、どうすれば値変数宣言の構文を修正できますか?

参考までに、ドメインモデルによって生成されたコードのサンプルフィールド/プロパティを次に示します。

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

3 に答える 3

82

オブジェクトの構造について何も知らずに、オブジェクトを「ダンプ」する汎用的な方法を定義しようとしていると思います。もしそうなら、あなたは物事を正しい方法で行っています。リフレクション(GetType()および関連するTypeクラスメソッド)を使用して、オブジェクトを検査し、その情報を返します。

GetFields()何も返さなかった理由は、適切なバインディングフラグを指定しなかった可能性があるためです。特に、パラメーターを受け取らないオーバーロードを呼び出すと、publicフィールドのみが返されます。プライベートフィールドが必要な場合は、具体的に要求する必要があります。

あなたの場合、はとフィールドGetFields(BindingFlags.NonPublic)を返しますが、GetProperties()はとプロパティを返します。_new_systemGauges_new_systemAlarmNew_systemAlarmNew_systemAlarm

見逃したもう1つの重要な要素は、取得するデータがタイプメタデータであるということです。の構造を定義し、class特定のインスタンスを定義しません。特定のインスタンスのプロパティの値を知りたい場合は、次のことを尋ねる必要があります。

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

タイプのメタデータの要素の1つがあるPropertyInfo場合は、そのタイプの任意のインスタンスでそのプロパティ値を要求できます。最初に使用したものと同じインスタンスである必要はありません。例えば:

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

技術的には、の結果をチェックしてGetIndexParameters、プロパティがインデックス付けされているかどうかを確認する必要があります。toのnullパラメーターGetValueは、実際にはインデックス値の配列です。

取得した値を変換するには、タイプキャストを使用するか、もう少し柔軟にしたい場合は、Convertクラスのメソッドを使用します。違いは、たとえば、shortプロパティがある場合、ボックス化されたshortが返されるため、 ;GetValue()としてタイプキャストすることはできません。int最初に開梱する必要がありますshort。を使用すると、整数に変換可能なプロパティから値Convert.ToInt32()を取得するために必要なすべての手順が実行されます。int

is参照型間の変換は、そのために使用できるため、より簡単ですas。これらは、「反映された」プロパティ値で期待するのと同じように機能します。

于 2012-03-15T17:11:20.807 に答える
2

GetProperties確かに正しい方法です。

コンパイラエラーを取り除くには、コードを次のように変更します。

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

PropertyInfoオブジェクトは特定のクラスインスタンスにバインドされていないため、値を取得するインスタンスを渡す必要があります。


標準の.NET命名規則に従うことを検討してください。

これにより、次のようになります。

NewSystemAlarmの代わりにNew_systemAlarm
newSystemAlarmまたは_newSystemAlarm代わりの_new_systemAlarm
NewTestInspectionExtensionBases代わりNew_testinspectionExtensionBases
NewTestInspectionIdNew_testinspectionId

于 2012-03-15T17:10:38.377 に答える
0

OpenAccessを使用している場合は、モデルクラスに関する完全な情報をいつでも自由に使用できます。そこにある情報はマッピングから取得されます。つまり、クラスを反映する必要はありません(オーバーヘッドはありません)。

すべてのクラスマッピング情報については、context.Metadata.PersistentTypesを参照するだけです。

于 2012-03-15T18:20:47.043 に答える