English 中文(简体)
评价一套在说明中界定的规则
原标题:Evaluating a set of rules defined in a string
  • 时间:2011-10-03 16:33:05
  •  标签:
  • c#

我建立了一种制度,以职能/反应形式简单地加以阐述,例如:

Check( Value ):ShowImage(@)|Check( Value ):OtherFunction(@)....and so on

<代码>Check为功能名称的,Value 为参数,ShowImage为反应功能的名称,@为切入层参数(以前功能的结果)。 管道将另一个功能/反应层分开,如果第一个<代码>,则会火烧。 核对(数值)功能一旦“核对”不满意(例如,如果参数未达到<代码>)。 检查条件是该功能无效,因此第一个功能/反应舱的对应部分没有执行,因此系统在等待找到执行正确反应的职能时,会保持审判功能。

The way the application should work is to evaluate each rule (similar to a JavaScript eval function) and take appropriate action based on function results.

At first glance, it looks complicated, because first of all I need to cast the string to the right real C# function that will actually process the condition. Therefore, depending on the function result, decide where to point to execute my Response function.

此外: 这只是一个例子,因为有*的功能,即“任何条件都是真实的”,而几乎所有情况下,这一功能是链条(违约功能)中的最后功能。

That s my problem, I can t realize what is the easiest way to cope with this problem. Maybe a chain of delegates? Lambdas? Anonymous stored into a structure...

您能否向我提供你的措施/建议? 何时开始?

最佳回答

视你是否愿意接受的程度而定,我要说,最可行的办法是,在你对所显示的投入进行调和之后,利用思考获取方法参考。

首先,你可以把问题分成小小小小小小小小小小问题。

Let s say you are aiming for something like this:

static void Main(string[] args)
{
    string rules = 
        "Check(Morning):Say(Good morning)|" +
        "Check(Afternoon):Say(Good afternoon)|" +
        "Check(Evening):Say(Good night)";

    // next, you need some **object instances** which will 
    // provide a context for your "test" and "action" methods.
    // you don t want to use static methods if you
    // went through the pain of defining such an architecture!

    // let s say that a "Tester" object has a "Check" method,
    // and an "Executor" object has a "Say" method:

    var tester = new Tester("Afternoon");
    var executor = new Executor();

    // since I suck at regular expressions,
    // I am using plain string methods to split
    // the expression into tokens. You might want
    // to add some validation

    foreach (var rule in rules.Split( | ))
    {
        var result = Parse(rule, tester, executor);
        if (result.TestPassed)
        {
            result.Execute();
            break;
        }
    }
}

上文使用的“结果”将具有这样的接口:

public interface IResult
{
    // returns true if a test is fulfilled
    bool TestPassed { get; }

    // executes the related action
    void Execute();
}

And, if you want to delegate actual actions to some unknown methods, a reasonable way to implement it would be something like this:

public class Result : IResult
{
    #region IResult Members

    private readonly Func<bool> _testMethod;
    public bool TestPassed
    {
        get { return _testMethod(); }
    }

    private readonly Action _actionMethod;
    public void Execute()
    {
        _actionMethod();
    }

    #endregion

    public Result(Func<bool> testMethod, Action actionMethod)
    {
        _testMethod = testMethod;
        _actionMethod = actionMethod;
    }
}

What s left is to use some reflection to get the actual methods out of your strings:

private static IResult Parse(string rule, object tester, object executor)
{
    // split into test/action
    var tokens = rule.Split( : );

    // extract the method/parameter part for each expression
    var test = GetMethodAndParams(tokens[0]);
    var action = GetMethodAndParams(tokens[1]);

    // use reflection to find actual methods
    var testMethod = tester.GetType().GetMethod(test.Method);
    var actionMethod = executor.GetType().GetMethod(action.Method);

    // return delegates which will simply invoke these methods
    return new Result
    (
        () => (bool)testMethod.Invoke(tester, new object[] { test.Param }),
        () => actionMethod.Invoke(executor, new object[] { action.Param })
    );
}

越来越多的是你的方案。 你们应当能够作为演习来填补失踪的部件。 如果存在问题,我可以稍后更新答案。

“GetMethodAndParams方法”应当将含有该方法名称及其作为便衣物的斜体的图形(或您的习惯类别)中显示的投入分解成图。

问题回答

它想像你想要一种模式,即TryParse()。 在此情况下,您将修改检查方法,使其具有价值(例如@)。

int result;

if(Check( Value , out result))
    ShowImage(result);
else(Check( Value2 , out result))
    OtherFunction(result);

Finally I m back here to post what I ve done few weeks ago to solve this situation. It was easy.

Regex类别提供了很少的选择,其中一个选择是Explicit Catpure>,所有形式(?)的溪流都可以作为强有力的分类参数处理,这样,如果名称的“Is NotEmptyorNull”集团当时就具备了这一功能,而且使用Enum.Parse(”)的形式可以推广。

Snipet:

Regex rx = new Regex(@"(?<function>Check|BooleanOp)( (?<param>[w]+) ){1}:(?<action>[w]+){1}", RegexOptions.ExplicitCapture);

Match m;
Dictionary<FunctionArray, String> actions = new Dictionary<FunctionArray, String>();

if((m=rx.Match(strStream)).Success)
{
   actions.Add((FunctionArray)Enum.Parse(typeof(FunctionArray), m.Groups["function"].value, true), m.Groups["param"].value);
}

当然,失去了行动部分,因此,我用能够处理作为作出决定来源的职能和价值观的专门建筑改进了理论。

感谢大家。 Ed.





相关问题
Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

NSArray s, Primitive types and Boxing Oh My!

I m pretty new to the Objective-C world and I have a long history with .net/C# so naturally I m inclined to use my C# wits. Now here s the question: I feel really inclined to create some type of ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

How to Use Ghostscript DLL to convert PDF to PDF/A

How to user GhostScript DLL to convert PDF to PDF/A. I know I kind of have to call the exported function of gsdll32.dll whose name is gsapi_init_with_args, but how do i pass the right arguments? BTW, ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...

热门标签