使用 ExpandoObject 传递动态参数

本文关键字:动态 参数 ExpandoObject 使用 | 更新日期: 2023-09-27 18:32:33

我有一些函数,其原型看起来像这样: public void doThings(string sql, dynamic dParams);

它使用这些参数执行某种 SQL 查询。我没有写它,但我必须使用它。当我做这样的事情时,它工作正常:

doThings("select * from SomeTable where myval1=@v1 and myval2=@v2",
        new
        {
            v1 = new Dapper.DbString()
            {
                Value = "yay",
                IsAnsi = true,
                Length = 50
            },
            v2 = new Dapper.DbString()
            {
                Value = "really",
                IsAnsi = true,
                Length = 32
            }
        });

但当我第一次将动态参数放入 ExpandoObject 时,情况并非如此:

dynamic dynParams = new ExpandoObject();
dynParams.v1 = new Dapper.DbString()
    {
        Value = "yay",
        IsAnsi = true,
        Length = 50
    }
doThings("query here", dynParams);  

然后,查询不返回任何结果。我不想调用doThings()并针对十种不同的场景编写该new块十次,我可能想要查询myval2myval3等等。我应该通过ExpandoObject,或者我应该以其他

使用 ExpandoObject 传递动态参数

方式通过其他方式来传递?

Dapper 默认不支持 Expandos,但您可以将 expando 传递给Dictionary<string,object>的构造函数,然后将其作为动态参数传递。

正如@Michael B所提到的,Dapper不支持Expandos作为参数。

如果您需要动态构建参数集,根据本文,您可以使用 DynamicParameters .

因此,您可以构建一个从dynParamsDynamicParameters的转换器,它看起来像:

dynamic dynParams = new ExpandoObject();
dynParams.v1 = new Dapper.DbString()
{
    Value = "yay",
    IsAnsi = true,
    Length = 50
};
var parameters = new Dapper.DynamicParameters();
((ExpandoObject)dynParams).ToList().ForEach(kvp => parameters.Add(kvp.Key, kvp.Value));

它认为这可能是一个不错的功能。

当您编写以下内容时,看起来doThings正在使用反射来获取所需的值:

new { 
    v1 = 1,
    v2 = "foo"
}

您正在创建具有两个属性 v1v2 的类型,但是当您使用 ExpandoObject your 不会ExpandoObject添加任何新属性(它的所有魔术行为都是编译器生成的东西)。

如果您想将doThing与编译时已知的属性一起使用,我知道没有问题。当属性在运行时已知时,我能想到的唯一方法是在运行时使用 Reflection.Emit 生成所需的匿名类型。看看这篇文章。