根據你想擁有可擴展的水平,我會說,最可擴展的方式是使用反射來獲取方法的引用,你已經解析輸入字符串之後。
您可以通過拆分您的問題分成更小的子問題開始。
比方說,你的目標是這樣的事情:
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;
}
}
}
A「結果」,因爲它的上面使用,那麼就會有一個這樣的接口:
public interface IResult
{
// returns true if a test is fulfilled
bool TestPassed { get; }
// executes the related action
void Execute();
}
而且,如果你想將實際行爲委託給某些未知的方法,實施它的合理方式將如下所示:
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;
}
}
剩下的就是用一些反射來獲取實際的方法,你的字符串:
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 })
);
}
也就是說,或多或少,你的程序的骨架。作爲練習,您應該能夠自己填寫缺失的部分。如果您有問題,我可以稍後更新答案。
A GetMethodAndParams
方法應該將輸入字符串拆分成一個包含方法名稱和它的參數爲純字符串的元組(或您的自定義類)。 Tester
和Executor
類也可以平凡地實現。
這並不完全清楚你的問題是什麼。如果我說得對,現在你有這個「字符串」代表一組規則和動作,應該使用C#解析並執行它?它需要看起來像這樣嗎?或者這只是一個建議? – Groo
你懂了!這個「字符串」是一組規則。然後將每一個解析爲一個C#函數,然後進行求值,如果函數找到一個「out」參數Check條件(想象我們正在「檢查」一個字典),那麼它的引用就是響應的參數功能。 –
我一直在使用NCalc進行一個不同但相當相似的項目。 NCalc允許您使用「自定義函數」,然後您可以捕捉它,但最終會評估爲數學表達式,因此您的規則集將不得不進行修改以支持該規則。無論如何,它有點像Eval函數,所以它可能對你有所幫助,所以你不必做很多解析工作,並可以在你的變量中包含數學公式。然後你可以像使用它(http://ncalc.codeplex.com/) – deepee1