I have a list of Actions.
public class Action {
public string Name { get; set; }
public DoWorkEventHandler DoWork{ get; set; }
}
That is populated on code.
list.Ad开发者_如何学JAVAd(new Action("Name", SomeRandomMethod));
...
When someone chooses an Action from that list it will execute the respective action.
private void ListBoxSelectionChanged(object sender, SelectionChangedEventArgs e) {
var item = (Action) ListBoxScripts.SelectedItem;
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += item.DoWork;
worker.RunWorkerAsync();
}
But I want to define and build this list from a DB. So How should I create an Action with a DoWorkEventHandler parameter when what I got from the DB is a string with the method name?
There are a number of ways you could do this.
You could declare an enum
containing all method names that are allowed to be called, then on startup using reflection build a dictionary mapping enums
to methodinfo
's. You'd store the enum in the database.
Another option would be to decorate classes/methods as below:
[ContainsScriptableMethod("MyClassIdentifyingName"] // or a number
class MyUserScriptableMethods
{
[ScriptableMethod("MyMethodIdentifyingName")] // Or just a number as an identifier
void MyMethod()
{
// Do non-malicious stuff.
}
}
When looking up a method to call you'd get a class ID from the database, then use reflection to get all classes that have the [ContainsScriptableMethod]
attribute with the correct Id, then do the same for looking up the method.
You could just have an attribute for the method if there's only a few defined classes that have methods that can be called/scripted.
Example code below:
// Enumerate all classes with the ContainsScriptableMethod like so
foreach(var ClassWithAttribute in GetTypesWithAttribute(Assembly.GetExecutingAssembly(), typeof(ContainsScriptableMethodAttribute))
{
// Loop through each method in the class with the attribute
foreach(var MethodWithAttribute in GetMethodsWithAttribute(ClassWithAttribute, ScriptableMethodAttribute))
{
// You now have information about a method that can be called. Use Attribute.GetCustomAttribute to get the ID of this method, then add it to a dictionary, or invoke it directly.
}
}
static IEnumerable<Type> GetTypesWithAttribute(Assembly assembly, Type AttributeType)
{
foreach(Type type in assembly.GetTypes())
{
if (type.GetCustomAttributes(AttributeType, true).Length > 0)
{
yield return type;
}
}
}
static IEnumerable<MethodInfo> GetMethodsWithAttribute(Type ClassType, Type AttributeType)
{
foreach(var Method in ClassType.GetMethods())
{
if (Attribute.GetCustomAttribute(AttributeType) != null)
{
yield Method;
}
}
}
精彩评论