Reputation: 3395
I'm not quite sure the correct way of asking this question, so I'm just going to go for it.
I am looking for the cleanest way of passing in "parameter sets" into a Method. For instance:
Dictionary<string, string> Parameters = new Dictionary<string, string>();
Parameters.Add("UserID", "12");
Parameters.Add("SiteID", "43");
CreateLog("Hello World!", Parameters);
public void CreateLog(string Message, Dictionary<string, string> Parameters)
{
...
}
However, I would like to do this in a much cleaner way and I'm sure there is some method of doing it that I can't think of. I could make a custom object that takes a string and an object, for instance:
public void CreateLog(string Message, params LogParameter[] Parameters)
{
...
}
Then I could create a new Log Parameter for each Parameter and pass it in, but I would like to be a bit more concise than that and avoid having to create all those new objects for something that (I think) should be simpler.
One possible solution is to do something like this:
CreateLog("Hello World!", new { UserID = 12, SiteID = 43 });
public void CreateLog(string Message, object Parameters)
{
...
}
This is similar to how C# ASP.NET creates URL variables/how DevExpress creates callbacks for their controls. But how do they get the values out of the object in the method?
Any thoughts?
Upvotes: 2
Views: 1416
Reputation: 14677
Here's the catch, how you can use reflection to get properties out of a Anonymous type passed as object to a method.
public void CreateLog(object parameters)
{
foreach(var property in parameters.GetType().GetProperties())
{
WriteLog(string.Format("{0} - {1}",property.Name, property.GetValue(parameters)));
}
}
Usage:
CreateLog(new {SiteID = 1, UserId = 2});
Upvotes: 1
Reputation: 239220
Three options as I see it:
Use a dictionary as you've already suggested.
Create a class that functions as a DTO and pass that:
public class LogParameters
{
public int UserId { get; set; }
public int SiteId { get; set; }
}
public void CreateLog(string message, LogParameters parameters)
Use an anonymous object, an approach you've also suggested. In your method, you'll have to rely on reflection to transform the object into something you can actually utilize.
Microsoft provides a way to do this via HtmlHelper.AnonymousObjectToHtmlAttributes
, but so you don't need a dependency on the System.Web.Mvc
namespace, the source for that method is as follows:
public static IDictionary<string, object> AnonymousObjectToHtmlAttributes(object htmlAttributes)
{
Dictionary<string, object> result;
var valuesAsDictionary = htmlAttributes as IDictionary<string, object>;
if (valuesAsDictionary != null)
{
result = new Dictionary<string, object>(valuesAsDictionary, StringComparer.OrdinalIgnoreCase);
}
else
{
result = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
if (htmlAttributes != null)
{
foreach (var prop in htmlAttributes.GetType().GetRuntimeProperties())
{
var value = prop.GetValue(htmlAttributes);
result.Add(prop.Name, value);
}
}
}
return result;
}
That should give you the inspiration you need to adapt it for your own code.
Personally, I generally go with approach 1 or 2 in these scenarios. The syntactic sugar of using an anonymous object is tempting, but if your method depends on the proper params being provided, it can be a crap shoot. Honestly, the dictionary approach suffers in this way as well, but at least there, you're not dealing with reflection.
Technically speaking, methods should be self-documenting, which means you should be passing in either individual named params or a class instance. That way, you have the assurance that what you expect to be available to your method is there, and the end-user of the method can see at a glance what's required to satisfy it. Neither a dictionary nor an anonymous object gives you either of these, and if you notice, the only times Microsoft uses anonymous objects as a param, the contents are completely optional, such as htmlAttributes
in a helper. If certain keys don't exist, then it's no big deal, since it's all optional anyways.
Upvotes: 1