If you're just looking for sparse syntax for the caller, you can use an anonymous type, similar to the way that jquery passes optional options around. Example:
public static void someFunction(object input)
{
foreach (var p in input.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public))
Console.WriteLine("{0}={1}", p.Name, p.GetValue(input));
}
The function itself is a little more messy, but for the caller, the syntax is pretty lightweight:
someFunction( new { Number = 3, Text = "Some text"});
output:
Number=3
Text=Some text
If you plan to do this a lot, you can make it a little less painful with an extension method. I named mine Extract()
, below:
using System;
using System.Linq;
using System.Collections.Generic;
using System.Reflection;
public static class ExtensionMethods
{
public static Dictionary<string, object> Extract<T>(this T input) where T : class
{
return input
.GetType()
.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.ToDictionary( p => p.Name, p => p.GetValue(input));
}
}
public class Program
{
public static void someFunction(object input)
{
var parameters = input.Extract(); //Magic
Console.WriteLine("There were {0} parameters, as follows:", parameters.Count);
foreach (var p in parameters)
{
Console.WriteLine("{0}={1}", p.Key, p.Value);
}
}
public static void Main()
{
someFunction(new { number = 3, text = "SomeText" } );
someFunction(new { another = 3.14F, example = new DateTime(2017, 12, 15) } );
}
}
Output on DotNetFiddle:
There were 2 parameters, as follows:
number=3
text=SomeText
There were 2 parameters, as follows:
another=3.14
example=12/15/2017 12:00:00 AM
The main downside with this approach is that you can't use interfaces or do anything to require that certain keys be present. Also, you have to use Reflection, which is a little bit more work. If you'd like to avoid these downsides, you could use the same approach but with a non-anonymous type, like this:
class SomeFunctionParams
{
public int Number { get; set; }
public string Text { get; set; }
}
public static void someFunction(SomeFunctionParams params)
{
Console.WriteLine("Number={0}", params.Number);
Console.WriteLine("Text={0}", params.Text);
}
...but then you'd lose the dynamic advantages of the anonymous type.
Another option is expose every possible key as an optional parameter, and only provide the ones you want:
void someFunction(int Number = default(int), string Text = default(string), DateTime SomeOtherParam = default(DateTime))
{
if (Number != default(int)) Console.WriteLine("Number={0}", Number);
if (Text != default(string)) Console.WriteLine("Text={0}", Text);
if (SomeOtherParam != default(DateTime)) Console.WriteLine("SomeOtherParam={0}", SomeOtherParam);
}
someFunction(Number : 3, Text : "Some text");