12

C# では、実行時までフィールドが不明な匿名型を宣言できるかどうかを調べたいと思います。

たとえば、キーと値のペアのリストがある場合、そのリストの内容に基づいて匿名型を宣言できますか? 私が取り組んでいる特定のケースは、パラメーターを Dapper に渡すことです。この場合、事前にパラメーターの数がわかりません。

List<Tuple<string, string>> paramList = new List<Tuple<string, string>>() {
    new Tuple<string, string>("key1", "value1"),
    new Tuple<string, string>("key2", "value2")
    ...
};

この List (または同等の Map) を、クエリ パラメータとして Dapper に渡すことができる匿名型に変換したいと考えています。したがって、理想的には、匿名型として定義されている場合、上記のリストは次のようになります。

new { key1=value1, key2=value2, ... }

StackOverflow で、宣言された後に匿名型を拡張すること (「extendo オブジェクト」)、またはオブジェクトの作成後に任意のフィールドを宣言することについて尋ねる質問をいくつか見てきましたが、それを行う必要はありません...必要なだけです型を事前に動的に宣言します。私の疑いでは、それが可能であるとしても、それにはいくらかの凝った反省が必要になるだろう.

私の理解では、コンパイラはコンパイル時にボンネットの下で匿名クラスの型を定義するため、そのクラスのフィールドが実行時まで利用できない場合、運が悪い可能性があります。私の使用例は、「拡張オブジェクト」を使用して任意のフィールドをいつでも定義することと実際には変わらないかもしれません。

または、(匿名クラスを宣言するのではなく) クエリ パラメーターを Dapper に渡すためのより良い方法を誰かが知っている場合は、それについても聞きたいです。

ありがとう!

アップデート

こちらからの連絡が遅くなり申し訳ありません!これらの回答はすべて素晴らしいものでした。皆さんにポイントを与えたいと思います。jbtule のソリューション (Sam Saffron による編集) を使用して IDynamicParameters を Dapper に渡すことになったので、彼に答えを与える必要があると感じました。他の回答も素晴らしく、私が尋ねた具体的な質問に答えてくれました。みんなの時間を本当にありがとう!

4

3 に答える 3

13

Dapper の作成者は、この問題を十分に認識していました。INSERTこの種の機能はUPDATEヘルパーにとって本当に必要です。

、およびメソッドはQueryパラメーターを受け取ります。これは、匿名型、具象型、または を実装するオブジェクトのいずれかです。ExecuteQueryMultipledynamicIDynamicParameters

public interface IDynamicParameters
{
    void AddParameters(IDbCommand command, Identity identity);
}

このインターフェースは非常に便利で、AddParametersSQL を実行する直前に呼び出されます。これにより、SQL に送信されるパラメーターを詳細に制御できるようになるだけではありません。コマンドにアクセスできるため、DB 固有の DbParameters をフックできます (DB 固有のコマンドにキャストできます)。これにより、テーブル値パラメーターなどのサポートが可能になります。

Dapper には、 という目的で使用できるこのインターフェースの実装が含まれていますDynamicParameters。これにより、連結された匿名パラメーター バッグと特定の値の追加の両方が可能になります。

メソッドAddDynamicParamsを使用して、匿名型を追加できます。

var p = new DynamicParameters();
p.AddDynamicParams(new{a = "1"});
p.AddDynamicParams(new{b = "2", c = "3"});
p.Add("d", "4")
var r = cnn.Query("select @a a, @b b, @c c, @d d", p);
// r.a == 1, r.b == 2, r.c == 3, r.d == 4
于 2011-09-15T20:53:39.557 に答える
11

C# では、実行時までフィールドが不明な匿名型を宣言できるかどうかを調べたいと思います。

匿名型はコンパイラによって生成されます。コンパイラが、コンパイラに認識されていないフィールド型を持つコンパイラ生成型を生成するかどうかを知りたいです。明らかにそうすることができません。あなたが正しく推測しているように、あなたは運が悪いです。

宣言された後に匿名型を拡張することについて尋ねる StackOverflow に関するいくつかの質問を見てきました (「extendo オブジェクト」)

通常、これらを「expando」オブジェクトと呼びます。

キーと値のペアのディクショナリに基づいて expando オブジェクトを作成する場合は、ExpandoObject クラスを使用してそれを行います。詳細については、この MSDN の記事を参照してください。

http://msdn.microsoft.com/en-us/magazine/ff796227.aspx

実行時に正真正銘の .NET クラスを生成したい場合は、それも可能です。あなたが正しく指摘しているように、そのためにはいくつかの派手な反省が必要です。やりたいことは、収集可能なアセンブリを作成することです (通常のアセンブリとは異なり、実行時にアセンブリを生成し、処理が完了するとガベージ コレクターによってクリーンアップされるため、いわゆる)。

収集可能なアセンブリを作成し、TypeBuilder を使用してそのアセンブリに型を出力する方法の詳細については、http://msdn.microsoft.com/en-us/library/dd554932.aspxを参照してください。

于 2011-09-15T20:31:59.063 に答える
7

匿名型は使用できません。匿名型は、実行時ではなくコンパイラによって生成されます。あなたは確かに使用することができdynamicます:

dynamic dynamicObj = new ExpandoObject();    
var objAsDict = (IDictionary<String, Object>)dynamicObj;

foreach(var item in paramList)
{
    objAsDict.Add(item.Item1, item.Item2);
}

次に、dynamicObj を通常のオブジェクトとして使用できます。

Console.WriteLine(dynamicObj.key1); // would output "value1"
于 2011-09-15T20:30:18.193 に答える