从数据库填充函数字典

时间:2013-09-15 02:18:30

标签: c# .net dictionary tuples

我正在研究MUD,目前命令处理程序是一个元组,它使用字符串readString和Player PlayerObj和switch语句来确定返回元组

public Tuple<string, Player> handleCMD(string readString, Player PlayerObj)
{
    Tuple<string, Player> returnTuple = new Tuple<string, Player>(readString, PlayerObj);
    string[] arguments = readString.Split(' ');

    switch (arguments[0].ToLower())
    {
        case "addchange":
            returnTuple = doAddChange(readString, PlayerObj);
            break;
        case "changes":
            returnTuple = doChanges(readString, PlayerObj);
            break;
        case "score":
            returnTuple = doScore(readString, PlayerObj);
            break;
        case "look":
            returnTuple = doLook(readString, PlayerObj);
            break;
        case "north":
            returnTuple = doWalk(arguments[0], PlayerObj);
            break;
        case "east":
            returnTuple = doWalk(arguments[0], PlayerObj);
            break;
        case "south":
            returnTuple = doWalk(arguments[0], PlayerObj);
            break;
        case "west":
            returnTuple = doWalk(arguments[0], PlayerObj);
            break;
        case "quit":
            returnTuple = doQuit(readString, PlayerObj);
            break;
        case "chat":
            returnTuple = doChat(readString, PlayerObj);
            break;
        case "say":
            returnTuple = doSay(readString, PlayerObj);
            break;
        case "who":
            returnTuple = doWho(readString, PlayerObj);
            break;
        case "tell":
            returnTuple = doTell(readString, PlayerObj);
            break;
        default:
            returnTuple = doHuh(readString, PlayerObj);
            break;
    }
    return returnTuple;
}

public Tuple<string, Player> doSay(string readString, Player PlayerObj)
{
    DBHandler dbHandler = new DBHandler();
    PlayerObj = dbHandler.GetPlayer(PlayerObj.PlayerName);
    string returnString;
    string[] arguments = readString.Split(' ');
    if (arguments.Count() > 1 && arguments[1] != string.Empty && arguments[1] != null && arguments[1] != "" && arguments[1] != " ")
    {
        readString = readString.Trim().Replace("say ", "");
        Message message = new Message(0, readString, PlayerObj.PlayerID, 0, 1, 1);
        returnString = string.Format("You say \"{0}\"", readString);
        foreach (int i in dbHandler.GetPlayersInRoom(PlayerObj.RoomID, PlayerObj.PlayerName))
            dbHandler.AddMessage(new Message(0, message.MessageText, message.SenderPlayerID, i, message.MessageType, message.Ticked));
    }
    else
        returnString = "[Syntax] : Say <Message>";
    return new Tuple<string, Player>(returnString, PlayerObj);
}

我想用数据库中的表填充的Dictionary替换switch语句,这样我就可以在数据库表中添加和禁用命令/别名而无需编辑代码

我试过这样做:

public Tuple<string, Player> handleCMD(string readString, Player PlayerObj)
{
    Tuple<string, Player> returnTuple = new Tuple<string, Player>(readString, PlayerObj);
    string[] arguments = readString.Split(' ');
    DBHandler dbHandler = new DBHandler();

    Dictionary<string, Delegate> cmdDictionary = new Dictionary<string, Delegate>();

    foreach (Command playerCommand in dbHandler.GetCommands())
        cmdDictionary.Add(playerCommand.CommandName, new Func<string, Player, Tuple<string, Player>>(playerCommand.CommandTuple));
    if (cmdDictionary[arguments[0]] != null)
        returnTuple = (Tuple<string, Player>)cmdDictionary[arguments[0]].DynamicInvoke(readString, PlayerObj);
    else
        returnTuple = doHuh(readString, PlayerObj);
    return returnTuple;
}

问题是我收到错误消息:

cmdDictionary.Add(playerCommand.CommandName, new Func<string, Player, Tuple<string, Player>>(playerCommand.CommandTuple));
'GWOService.Command.CommandTuple' is a 'property' but is used like a 'method'

playerCommand.CommandName是一个字符串=“doSay”或“doHuh”或者元组的名称,但以下是有效的:

cmdDictionary.Add(playerCommand.CommandName, new Func<string, Player, Tuple<string, Player>>(doSay/*playerCommand.CommandTuple*/));

更新

所以我再次尝试了以下内容:

public Tuple<string, Player> handleCMD(string readString, Player PlayerObj)
{
    Tuple<string, Player> returnTuple = new Tuple<string, Player>(readString, PlayerObj);
    string[] arguments = readString.Split(' ');
    DBHandler dbHandler = new DBHandler();
    Dictionary<string, Delegate> cmdDictionary = new Dictionary<string, Delegate>();
    foreach (Command playerCommand in dbHandler.GetCommands())
    {
        try
        {
            MethodInfo method = GetType().GetMethod(playerCommand.CommandTuple);
            //Func<string, Player, Tuple<string, Player>> func = ( ) => { return (Tuple<string, Player>)(this.GetType().GetMethod(playerCommand.CommandTuple).Invoke(this, new object[0])); }
            Func<string, Player, Tuple<string, Player>> func = (Func<string, Player, Tuple<string, Player>>)Delegate.CreateDelegate(typeof(Func<string, Player, Tuple<string, Player>>), method);
            cmdDictionary.Add(playerCommand.CommandName, new Func<string, Player, Tuple<string, Player>>(func));
        }
        catch (Exception e)
        {
            dbHandler.LogEntry(PlayerObj, e.ToString());
        }
    }
    if (cmdDictionary[arguments[0]] != null)
        returnTuple = (Tuple<string, Player>)cmdDictionary[arguments[0]].DynamicInvoke(readString, PlayerObj);
    else
        returnTuple = doHuh(readString, PlayerObj);

    //switch (arguments[0].ToLower())
    //{
    //    case "addchange":
    //        returnTuple = doAddChange(readString, PlayerObj);
    //        break;
    //    case "changes":
    //        returnTuple = doChanges(readString, PlayerObj);
    //        break;
    //    case "score":
    //        returnTuple = doScore(readString, PlayerObj);
    //        break;
    //    case "look":
    //        returnTuple = doLook(readString, PlayerObj);
    //        break;
    //    case "north":
    //        returnTuple = doWalk(arguments[0], PlayerObj);
    //        break;
    //    case "east":
    //        returnTuple = doWalk(arguments[0], PlayerObj);
    //        break;
    //    case "south":
    //        returnTuple = doWalk(arguments[0], PlayerObj);
    //        break;
    //    case "west":
    //        returnTuple = doWalk(arguments[0], PlayerObj);
    //        break;
    //    case "quit":
    //        returnTuple = doQuit(readString, PlayerObj);
    //        break;
    //    case "chat":
    //        returnTuple = doChat(readString, PlayerObj);
    //        break;
    //    case "say":
    //        returnTuple = doSay(readString, PlayerObj);
    //        break;
    //    case "who":
    //        returnTuple = doWho(readString, PlayerObj);
    //        break;
    //    case "tell":
    //        returnTuple = doTell(readString, PlayerObj);
    //        break;
    //    default:
    //        returnTuple = doHuh(readString, PlayerObj);
    //        break;
    //}
    return returnTuple;
}

但是我收到了错误:

第25行

Func<string, Player, Tuple<string, Player>> func = (Func<string, Player, Tuple<string, Player>>)Delegate.CreateDelegate(typeof(Func<string, Player, Tuple<string, Player>>), method);

System.ArgumentException: Cannot bind to the target method because its signature or security transparency is not compatible with that of the delegate type.
at System.Delegate.CreateDelegate(Type type, MethodInfo method, Boolean throwOnBindFailure)
at System.Delegate.CreateDelegate(Type type, MethodInfo method)
at GWOService.CmdHandler.handleCMD(String readString, Player PlayerObj) in \Projects\GodWarsOxide\GWOService\CmdHandler.cs:line 25

2 个答案:

答案 0 :(得分:2)

第一次错误尝试:

cmdDictionary.Add(playerCommand.CommandName, new Func<string, Player, Tuple<string, Player>>(playerCommand.CommandTuple));

第二次错误尝试:

returnTuple = (System.Tuple<string,GWOService.Player>)cmdDictionary[arguments[0]].DynamicInvoke(readString, PlayerObj);

我认为这可行,但尚未测试

答案 1 :(得分:2)

您可以使用GetMethod获取您需要通过名称

调用的方法
this.GetType().GetMethod("doSay")

然后,您可以使用所需参数在Func的{​​{1}}命令上创建DelegateInvoke并返回类型

MethodInfo

包装它以使其可重复使用

var function = new Func<string, Player, Tuple<string, Player>>((arg1, arg2) => (Tuple<string, Player>)this.GetType().GetMethod("doSay").Invoke(this, new object[] { arg1, arg2 })));

然后您可以将这些内容添加到public Func<string, Player, Tuple<string, Player>> CreateFunction(string methodName) { if (this.GetType().GetMethods().Any(x => x.Name == methodName)) { return new Func<string, Player, Tuple<string, Player>>((arg1, arg2) => (Tuple<string, Player>)this.GetType().GetMethod(methodName).Invoke(this, new object[] { arg1, arg2 })); } return null; }

Dictionary

或来自您 var functions = new Dictionary<string, Func<string, Player, Tuple<string, Player>>>(); functions.Add("Say",CreateFunction("doSay"));

Database

然后你可以随时打电话给他们

foreach (Command playerCommand in dbHandler.GetCommands())
{
    if (!functions.ContainsKey(playerCommand.CommandName))
    {
        functions.Add(playerCommand.CommandName, CreateFunction(playerCommand.CommandTuple));
    }
}

注意:

我建议用一个好的类代替 var result = functions["Say"]("Hello", new Player()); ,而不是像下面一样,因为在整个应用程序中处理它会不那么痛苦

Tuple<sting, Player>