NoLifeKing
NoLifeKing

Reputation: 1939

Extension method with dynamic named parameters

I'm currently writing an extension to replace the normal string.Format with my FormatNamed-function.

So far I have got this code, but I want to change the way to input the parameters

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

Not the prettiest of replaces, but it does the job.

Anyway. I want to change so I can execute it with

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

Is there any way I can do this? I have tried googling for dynamic named parameters with no good results.

Upvotes: 2

Views: 1395

Answers (2)

D Stanley
D Stanley

Reputation: 152654

I have tried googling for dynamic named parameters with no good results

That's because the capability does not exist. Think about it - how would the function know what to do if the parameters and their names were not known at compile time? The closest thing I can think of is using params which gives you an array of values, but they must all be the same type, and you can still access them by a given name (and index value).

I'd stick with the method you're currently using:

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

That creates an anonymous type with the properties specified, which should work fine with your existing code. Plus it's only a few extra characters to type.

Also note that dynamic doesn't buy you anything here since it's used to access properties directly without using reflection. Since you're using reflection to get the propeties you can just use object.

Upvotes: 2

p.s.w.g
p.s.w.g

Reputation: 149108

You won't be able to specify an arbitrary number of dynamic, named parameters. that's just not something that C# supports. Your existing code seems okay to me, although I don't see the need for the dynamic parameter. This will work just as well:

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

And then calling it as:

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

Although I really wouldn't advise using this sort of method for constructing SQL (it won't save you from SQL injection attacks at all), the method itself is sound.

Upvotes: 5

Related Questions