1

実行時に IScriptable オブジェクトに対してコマンドを実行する Command クラスがあります。

[
    XmlInclude(typeof(CommandPositionSettings)),
]
public abstract class CommandSettings
{
    public List<Command> Parameters = new List<Command>(4);

    public abstract Command Load();
}

public abstract class Command
{
    public List<Command> Parameters = new List<Command>(4);

    public Command(CommandSettings settings) 
    {
        Parameters = settings.Parameters;
    }

    public abstract void Execute(IScriptable scriptableObject);
    public abstract int GetArgumentCount();
    public abstract CommandSettings Write();
}

これは、Position などの特定のコマンドでうまく機能します。

public class CommandPosition : Command
{
    public CommandPosition(CommandPositionSettings settings)
        :base(settings = settings == null ? new CommandPositionSettings() : settings)
    {
        if (settings == null)
        {
            settings = new CommandPositionSettings();
        }
    }

    public override void Execute(IScriptable scriptableObject)
    {
        Vector3 position = new Vector3();
        position.X = Parameters[0].Execute();
        position.Y = Parameters[1].Execute();
        position.Z = Parameters[2].Execute();

        scriptableObject.Position = position;
    }

    public override int GetArgumentCount()
    {
        return 3;
    }

    public override CommandSettings Write()
    {
        CommandPositionSettings settings = new CommandPositionSettings();

        settings.Parameters.AddRange(Parameters);

        return settings;
    }
}

IScriptable を要求するのではなく、値を返すだけでよい別の種類のコマンドを実行しようとするまでは。上記のコードでは、位置の X、Y、および Z 値が取得される場所になります。

この時点では、各パラメーターを float として格納しても問題ありませんが、値を返すよりももう少し複雑なことをしたい場合があります。たとえば、コマンドが実行されるたびに 2 つの値の間でランダム化します。

public class CommandRandom : Command
{
    public CommandRandom(CommandRandomSettings settings)
        : base(settings = settings == null ? new CommandRandomSettings() : settings)
    {
        if (settings == null)
        {
            settings = new CommandRandomSettings();
        }
    }

    public override float Execute()
    {
        return ToolBox.Random.NextFloat(Parameters[0], Parameters[1]);
    }

    public override int GetArgumentCount()
    {
        return 2;
    }

    public override CommandSettings Write()
    {
        CommandPositionSettings settings = new CommandPositionSettings();

        settings.Parameters.AddRange(Parameters);

        return settings;
    }
}

このコマンドは、ランダムな浮動小数点数を返すためにのみ必要であり、IScriptable オブジェクトに直接影響を与えることはありません。

現在、同じクラスからそれらを派生させているもう 1 つの理由は、コマンド ライン文字列が解釈されると、Command(para0, para1...paraN)の一致する形式ごとに新しい Command が作成されることです。

Command は、別の Command 内にネストすることもできます。

Command( para0 , para1...paraN)ここで: para1 = Command(para0, para1...paraN)

では、値を返すためだけに必要なネストされた Command と、IScriptable オブジェクト自体に直接影響する Command をどのように区別すればよいでしょうか?

4

1 に答える 1

0

次のようなジェネリック型を使用して解決できます。

public interface IScriptable
{
    Vector3 Position;
}

public abstract class CommandSettings<T>
{
    public List<Command<T>> Parameters = new List<Command<T>>(4);

    public abstract Command<T> Load();
}

public class CommandRandomSettings : CommandSettings<float>
{
    public Command<float> Load()
    {
        return null;
    }
}

public class CommandPositionSettings : CommandSettings<object>
{
    public Command<object> Load()
    {
        return null;
    }
}

public abstract class Command<T>
{
    public List<Command<T>> Parameters = new List<Command<T>>(4);

    public Command(CommandSettings<T> settings)
    {
        Parameters = settings.Parameters;
    }

    public abstract T Execute(IScriptable scriptableObject);
    public abstract int GetArgumentCount();
    public abstract CommandSettings<T> Write();
}

public class CommandRandom : Command<float>
{
    public CommandRandom(CommandRandomSettings settings)
        : base(settings = settings == null ? new CommandRandomSettings() : settings)
    {
        if (settings == null)
        {
            settings = new CommandRandomSettings();
        }
    }

    public override float Execute()
    {
        return 0.0f;
    }

    public override int GetArgumentCount()
    {
        return 2;
    }

    public override CommandSettings<float> Write()
    {
        CommandRandomSettings settings = new CommandRandomSettings();

        settings.Parameters.AddRange(Parameters);

        return settings;
    }
}

public class CommandPosition : Command<object>
{
    public CommandPosition(CommandPositionSettings settings)
        : base(settings = settings == null ? new CommandPositionSettings() : settings)
    {
        if (settings == null)
        {
            settings = new CommandPositionSettings();
        }
    }

    public override object Execute(IScriptable scriptableObject)
    {
        Vector3 position = new Vector3();
        position.X = Parameters[0].Execute();
        position.Y = Parameters[1].Execute();
        position.Z = Parameters[2].Execute();

        scriptableObject.Position = position;
    }

    public override int GetArgumentCount()
    {
        return 3;
    }

    public override CommandSettings<object> Write()
    {
        CommandPositionSettings settings = new CommandPositionSettings();

        settings.Parameters.AddRange(Parameters);

        return settings;
    }
}

void残念ながら、この場合、型パラメーターとして渡すことはできません。上記のサンプルでは、​​代わりにオブジェクトを使用しました。Execute(IScriptable scriptableObject)メソッドは単純に を返すことができますnull

于 2013-04-19T12:19:16.967 に答える