从字符串构建DoWorkEventHandler

时间:2011-06-16 14:15:37

标签: c# reflection backgroundworker

我有一系列操作。

public class Action {
    public string Name { get; set; }
    public DoWorkEventHandler DoWork{ get; set; }
}

这是在代码上填充的。

list.Add(new Action("Name", SomeRandomMethod));
...

当有人从该列表中选择一个动作时,它将执行相应的动作。

private void ListBoxSelectionChanged(object sender, SelectionChangedEventArgs e) {
    var item = (Action) ListBoxScripts.SelectedItem;
    BackgroundWorker worker = new BackgroundWorker();
    worker.DoWork += item.DoWork;
    worker.RunWorkerAsync();
}

但我想从数据库中定义和构建此列表。那么当我从DB获取的是带有方法名称的字符串时,我应该如何用DoWorkEventHandler参数创建一个Action?

1 个答案:

答案 0 :(得分:2)

有很多方法可以做到这一点。

您可以声明包含允许调用的所有方法名称的enum,然后在启动时使用反射构建将enums映射到methodinfo的字典。您将枚举存储在数据库中。

另一种选择是装饰类/方法,如下所示:

[ContainsScriptableMethod("MyClassIdentifyingName"] // or a number
class MyUserScriptableMethods
{
    [ScriptableMethod("MyMethodIdentifyingName")] // Or just a number as an identifier
    void MyMethod()
    {
        // Do non-malicious stuff.
    }
}

当查找一个方法来调用你从数据库中获取一个类ID时,然后使用反射来获取具有正确Id的[ContainsScriptableMethod]属性的所有类,然后执行相同的查找方法

如果只有少数定义的类具有可以调用/编写脚本的方法,那么您可以拥有该方法的属性。

以下示例代码:

// 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;
        } 
   }
}