tags:

views:

115

answers:

3

Say, I have an XML String like this,

<METHOD>foo</METHOD>
<PARAM1>abc</PARAM1>
<PARAM2>def</PARAM2>
...
<PARAM99>ghi</PARAM99>
<PARAM100>jkl</PARAM100>

and I have a method

void foo(String param1, String param2, ..., String param99, String param100)
{
...
}

Is there any easy way for me to map this string to a real method call with the params matching the param names of the method in C#?

A: 

edit If you have to match the names in the constructor. Just throw the constructor away, as it is not a list of name/values but just a list of required objecttypes, and names aren't necessary. Use properties to match between the xml element name and the field in the class.

Jan Jongboom
Thanks Jan. But there is no guarantee that the order of the parameter in the data is the same as the method parameters.
gilbertc
See my edit
Jan Jongboom
+8  A: 

Assuming you know the type, have an instance of it, and that the method is actually public:

string methodName = parent.Element("METHOD").Value;
MethodInfo method = type.GetMethod(methodName);

object[] arguments = (from p in method.GetParameters()
                      let arg = element.Element(p.Name)
                      where arg != null
                      select (object) arg.Value).ToArray();

// We ignore extra parameters in the XML, but we need all the right
// ones from the method
if (arguments.Length != method.GetParameters().Length)
{
    throw new ArgumentException("Parameters didn't match");
}

method.Invoke(instance, arguments);

Note that I'm doing case-sensitive name matching here, which wouldn't work with your sample. If you want to be case-insensitive it's slightly harder, but still doable - personally I'd advise you to make the XML match the method if at all possible.

(If it's non-public you need to provide some binding flags to the call to GetMethod.)

Jon Skeet
Point is, you do not match the param names.
Jan Jongboom
Ah, I see. Okay, fixing...
Jon Skeet
+2  A: 

How about something like this:

 public void Run(XmlElement rootElement)
 {
  Dictionary<string, string> xmlArgs = new Dictionary<string,string>(StringComparer.OrdinalIgnoreCase);
  foreach( XmlElement elem in rootElement )
   xmlArgs[elem.LocalName] = elem.InnerText;

  MethodInfo mi = this.GetType().GetMethod(xmlArgs["METHOD"]);

  List<object> args = new List<object>();
  foreach (ParameterInfo pi in mi.GetParameters())
   args.Add(xmlArgs[pi.Name]);

  mi.Invoke(this, args.ToArray());
 }
csharptest.net