具有动态命名参数的扩展方法

时间:2013-08-12 13:55:52

标签: c# string extension-methods

我目前正在使用我的string.Format函数编写替换普通FormatNamed的扩展程序。

到目前为止,我已经有了这段代码,但我想改变输入参数的方式

void Main()
{
    string sql = "SELECT {fields} FROM {table} WHERE {query}"
        .FormatNamed(new { fields = "test", table = "testTable", query = "1 = 1" });
    Console.WriteLine(sql);
}

public static class StringExtensions
{
    public static string FormatNamed(this string formatString, dynamic parameters)
    {
        var t = parameters.GetType();
        var tmpVal = formatString;
        foreach(var p in t.GetProperties())
        {
            tmpVal = tmpVal.Replace("{" + p.Name + "}", p.GetValue(parameters));
        }
        return tmpVal;
    }
}

不是最漂亮的替换,但它确实起到了作用。

反正。我想改变所以我可以用

执行它
.FormatName(field: "test", table: "testTable", query: "1 = 1");

我有什么方法可以做到这一点?我已经尝试使用谷歌搜索动态命名参数,没有很好的结果。

2 个答案:

答案 0 :(得分:5)

您将无法指定任意数量的动态命名参数。这不是C#支持的东西。你现有的代码对我来说似乎没问题,虽然我认为不需要dynamic参数。这也可行:

public static string FormatNamed(this string formatString, object parameters)
{
    var t = parameters.GetType();
    var tmpVal = formatString;
    foreach(var p in t.GetProperties())
    {
        tmpVal = tmpVal.Replace("{" + p.Name + "}", p.GetValue(parameters));
    }
    return tmpVal;
}

然后将其称为:

string sql = "SELECT {fields} FROM {table} WHERE {query}"
    .FormatNamed(new { fields = "test", table = "testTable", query = "1 = 1" });

虽然我真的不建议使用这种方法来构造SQL(它根本不会让你免于SQL injection攻击),但这种方法本身就是合理的。

答案 1 :(得分:2)

  

我尝试使用Google搜索动态命名参数但效果不佳

那是因为该功能不存在。想一想 - 如果在编译时不知道参数及其名称,函数将如何知道该怎么做?我能想到的最接近的事情是使用params,它为您提供了一个数组值,但它们必须都是相同的类型,您仍然可以通过给定的名称访问它们(和指数值)。

我坚持使用您目前正在使用的方法:

.FormatName(new {field = "test", table = "testTable", query = "1 = 1"});

这会创建一个具有指定属性的匿名类型,它应该可以与现有代码一起使用。另外,它只需输入几个额外的字符。

另请注意,dynamic不会在此处购买任何内容,因为它用于直接访问属性而不使用反射。由于您使用反射来获得性能,因此您可以使用object