I’ve been tinkering with a CMS that I’m making as a personal project and I have got to a point that I am stuck on.
Basically I have a plugin manager that loads assemblies at runtime, looks for methods marked with a custom attribute and makes these methods available to be called from a template engine I have wrote.
I have the template engine parsing the template into expressions which get compiled into a function that I can cache and call. There are little bits of code within this template that are parsed to do different things like call a method on a plugin.
Example of the template code:
So far I have this parsed correctly, I have the method name and parameters as strings, ints, bools etc..
The plugin manager I have wrote is working fine too but I’m having trouble wiring the two together.
Say for example this is a plugin class:
[Plugin(Name="Test")]
public class TestPlugin
{
private DateTime _startTime;
public TestPlugin()
{
_startTime = DateTime.Now;
}
[TemplateAction]
public string Test(int number, string testString)
{
return "TEST";
}
}
I need to be able to call Test() from my parsed template and pass in any parameters from the template to the method. I have created a System.Delegate from the method marked with the attribute and added an expression within the template engine as part of the cached method to call the Test().
What I don’t know is how to pass in the parsed parameters from the template into the method. I tried to create an object[] and pass that into DynamicInvoke on the delegate but it complained about argument mismatch so I’m a bit stuck. I’m not sure if you can pass object[] into a method that has (params object[] args) as a signature via expressions.
Performance is also a concern with DynamicInvoke so if there is a way to accomplish this without using DynamicInvoke or create something I can cache that would be great.
Sorry if its unclear, any questions feel free to ask.
Any help is much appreciated.
Rick.
UPDATE
Okay after some thinking and thanks to D Stanley I did this.
foreach (var method in type.GetMethods().Where(x => x.GetCustomAttributes(typeof(TemplateActionAttribute), true).Length > 0))
{
if (method.ReturnType != typeof(string)) continue;
PluginTemplateActions.Add(method.Name, o => (string)method.Invoke(plugin, o));
}
So far it works just the way I want but will this also be quicker than DynamicInvoke?
You could use reflection: