簡體   English   中英

是否可以使用變量/動態字段集在C#中聲明匿名類型?

[英]Is it possible to declare an anonymous type in C# with a variable/dynamic set of fields?

在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 objects”),或者在創建對象后聲明任意字段,但我不需要這樣做......我只是需要一次性地動態聲明類型。 我懷疑它是否需要一些花哨的反思,如果可能的話。

我的理解是編譯器在編譯時為引擎定義了一個匿名類的類型,所以如果該類的字段在運行時才可用,我可能會運氣不好。 事實上,我的用例實際上與使用“extendo對象”定義任意字段無關。

或者,如果有人知道更好的方法將查詢參數傳遞給Dapper(而不是聲明一個匿名類),我也很想知道這一點。

謝謝!

UPDATE

抱歉延遲回到這個! 這些答案都很棒,我希望我能給大家一點。 我最終使用了jbtule的解決方案(由Sam Saffron編輯),將IDynamicParameters傳遞給Dapper,所以我覺得我必須給他答案。 其他答案也很好,並回答了我提出的具體問題。 我非常感謝大家的時間!

Dapper的創作者非常清楚這個問題。 INSERTUPDATE助手確實需要這種功能。

QueryExecuteQueryMultiple方法接受dynamic參數。 這可以是匿名類型,具體類型或實現IDynamicParameters的對象。

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

這個界面非常方便,在運行任何SQL之前調用AddParameters 這不僅可以豐富地控制發送到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

在C#中,我想弄清楚是否可以聲明一個匿名類型,其中字段在運行時才知道。

匿名類型由編譯器生成。 您想知道編譯器是否會生成編譯器生成的類型, 其中包含編譯器不知道的字段類型 顯然它不能這樣做; 正如你猜測的那樣,你運​​氣不好。

我已經在StackOverflow上看到幾個問題,詢問在聲明它們之后擴展匿名類型(“extendo objects”)

我們通常稱這些“expando”對象。

如果你想要做的是基於鍵值對的字典創建一個expando對象,那么使用ExpandoObject類來做到這一點。 有關詳細信息,請參閱此MSDN文章:

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

如果你想要做的是在運行時生成一個真正的.NET類,你也可以這樣做。 正如您所正確指出的那樣,您需要一些花哨的反思才能這樣做。 你想要做的是制作一個可收集的程序集(所謂的,因為與普通程序集不同,你在運行時生成它,垃圾收集器會在你完成它時清理它。)

有關如何使用TypeBuilder創建可收集程序集並向其中發出類型的詳細信息,請參閱http://msdn.microsoft.com/en-us/library/dd554932.aspx

您不能使用匿名類型。 匿名類型由編譯器生成,而不是在運行時生成。 你當然可以使用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"

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM