动态如果条件

时间:2014-11-29 02:47:00

标签: c# logic

尝试在线搜索但到目前为止没有运气

基本上我允许用户创建一个选择表达式,例如

TargetHealthLessThen20 TargetAboutToUsePotion

这些是针对枚举存储的,然后作为字符串表达式存储在数据库中,例如

" TargetHealthLessThen20 || TargetAboutToUsePotion"

现在我有每个枚举的方法来检查它的条件,即

 public bool IsTargetHealthLessThen20(Target target)
 {
      // do login
 }

 public bool IsTargetAboutToUsePotion(Target target)
 {
     // do login
 }

我希望能够编写一个动态的If语句来调用这些方法并放入条件,例如

 if("IsTargetHealthLessThen20(target) || IsTargetAboutToUsePotion(target)")
 {
       // Perform Action
 }

关于最佳解决方法的任何想法?

3 个答案:

答案 0 :(得分:1)

虽然由于性能原因我不一定会推荐以下内容,但它会做你想要的。

如果你总是应用你的目标而只是你的目标,你可以预先定义一类评估方法,然后传入一个字符串方法名称列表来评估这些方法。

void Main()
{
    var inputs = new List<string>();
    inputs.Add("MethodA");
    inputs.Add("MethodB");

    var results = Evaluate(inputs, "target");
    Console.WriteLine(results);
}

public bool Evaluate(List<string> predicates, string target)
{
    var methods = new Methods();

    var tempResult = false;

    foreach (var pred in predicates)
    {
        var method = methods.GetType().GetMethod(pred);
        if (method == null)
        throw new InvalidOperationException(
            string.Format("Unknown method {0}.", pred));

        tempResult = (bool)typeof(Methods).GetMethod(pred).Invoke(methods, new [] {target});
        if (!tempResult) break;

        continue;
    }

    return tempResult;
}

public class Methods
{
    public bool MethodA(string target)
    {
        return target == "target";
    }

    public bool MethodB(string target)
    {
        return target == "not a target";
    }
}

此特定评估功能将评估AND条件。您需要更改OR条件的评估逻辑。理论上,您可以检查字符串并根据字符串中的运算符调用不同的方法。

修改

避免反射的第二个选项是创建一个Dictionary,将您的方法的字符串名称映射到方法本身。这将允许您在没有反射的情况下实现相同的结果,尽管您必须保持字典同步。另一方面,您可以获得额外的编译时检查而无需反射开销。

private static readonly Methods _methodsInstance = new Methods();

private static Dictionary<string, Func<string, bool>> _methods = new Dictionary<string, Func<string, bool>>()
{
    { "MethodA", _methodsInstance.MethodA },
    { "MethodB", _methodsInstance.MethodB },
};

public bool Evaluate(List<string> predicates, string target)
{
    var tempResult = false;

    foreach (var pred in predicates)
    {   
        tempResult = _methods[pred](target);
        if (!tempResult) break;
        continue;
    }

    return tempResult;
}

答案 1 :(得分:0)

我认为这是困难的。因为您不知道目标参数值。如果你知道参数值,你可以使用reflect通过表达式字符串调用方法。

答案 2 :(得分:0)

我想我只有你正在寻找的答案,因为我过去几乎需要完全相同的事情:

你所拥有的是C#代码,所以你需要像对待它一样对待它:)

  1. 创建一个类似

    的界面

    interface ICondition { bool Evaluate(); }

  2. 现在使用您在那里的文本将其编译成一个类。 像这样: using YourProgramNamespace; class myCondition : ICondition { bool Evaluate() { return {0} ; } } 要传递更多参数,只需更改接口以允许匹配参数。 如果您不想要多个接口,请按以下方式进行:

    using YourProgramNamespace; class myCondition : ICondition { bool Evaluate(params object[] parameters) { return {0} ; } } 在你的文本中,你只需这样写: TargetHasLessThan20Hp((TargetType的)参数[0])

  3. 将{0}替换为您已有的条件文本。

    1. 使用C#编译器编译代码。 http://msdn.microsoft.com/de-de/library/microsoft.csharp.csharpcodeprovider%28v=vs.110%29.aspx 有关如何使用它的教程绰绰有余,而且它的用法并不那么难。

    2. 当您将类编译成Dll加载它并找到带反射的类型时,这也不难,并且有大量的教程。只需使用yourAssembly.GetTypes()并从那里开始

    3. 使用Activator.CreateInstance实例化您拥有的类型

    4. 然后只需调用evaluate函数,它将返回true或false。

    5. 为了获得更好的性能,请不要每次编译,直到条件文本实际发生变化。

    6. 需要更多信息?只需询问,我就会编辑我的答案或在评论中发布。