gpt4 book ai didi

C# - 以类型安全的方式将输入对象映射到效果对象

转载 作者:行者123 更新时间:2023-12-03 17:23:06 25 4
gpt4 key购买 nike

我试图解决的问题在概念上非常简单。我会用游戏来解释它,但我相信这个概念适用于任何具有输入、效果关系的对象:
能力由输入对象列表和效果对象列表组成。输入对象定义了用户交互的类型(例如选择地面瓦片或选择单元),每个输入对象将从用户那里获得特定类型的目标(例如瓦片或单元)。效果对象定义对特定类型目标的效果(例如移动到地砖或损坏单位)。
在代码中使用能力将包括:

  • 依次提示用户输入对象(等待用户完成每个对象的输入,然后再继续下一个对象)
  • 顺序执行效果(每个效果将从映射到的输入对象中获取数据)

  • 因此,定义能力的示例可能是:
    Ability: {
    Inputs: {
    Select Tile,
    Select Unit
    }

    Effects: {
    Move to (input 1),
    Deal 10 damage (input 2)
    }
    }
    理想情况下,我想让从输入到效果类型安全的映射,因为每种效果类型都有它所期望的目标数据类型(例如瓷砖或单元)。
    这是我编写的代码示例,用于表示代码中的 Action 、输入和效果对象:
        public class AbilityData
    {
    List<InputData<Target>> inputs;

    List<AbilityEffect> effects;

    public void exampleCreate()
    {
    BaseInputData<Tile> input = new TileSelectData();
    inputs.Add(input);

    effect = new List<AbilityEffect>();
    BaseAbilityEffect<Tile> effect = new BaseAbilityEffect<Tile>(new TileEffect(), input);
    effects.Add(effect);
    }
    public void exampleRun()
    {
    foreach (InputData<AbilityInput> input in inputs)
    {
    input.promptInput();
    }

    foreach (AbilityEffect effect in effects)
    {
    effect.execute();
    }
    }
    }
    public interface AbilityEffect
    {
    void execute();
    }

    public class BaseAbilityEffect<T> : AbilityEffect where T : Target
    {
    InputData<T> input;

    TargetEffect<T> effect;

    public BaseAbilityEffect(TargetEffect<T> tEffect, InputData<T> input) {
    this.input = input;
    this.effect = tEffect;
    }

    public void execute()
    {
    effect.execute(input.getInput());
    }
    }

    public class TargetEffect<T> where T : Target
    {
    public virtual void execute(T input) { }
    }

    public class UnitEffect : TargetEffect<Unit>
    {
    public override void execute(Unit unit)
    {
    // Do something on the unit
    }
    }

    public class TileEffect : TargetEffect<Tile>
    {
    public override void execute(Tile tile)
    {
    // Do something on the tile
    }
    }

    public interface InputData<out T>
    {
    void promptInput();

    T getInput();
    }

    public abstract class BaseInputData<T> : InputData<T> where T : Target
    {
    public abstract T getInput();

    public abstract void promptInput();
    }

    public class TileSelectData : BaseInputData<Tile>
    {
    public override Tile getInput()
    {
    // Return the stored input
    }

    public override void promptInput()
    {
    // prompt for the input and store it.
    }
    }

    public class UnitSelectData : BaseInputData<Unit>
    {
    public override Unit getInput()
    {
    // Return the stored input
    }

    public override void promptInput()
    {
    // prompt for the input and store it.
    }
    }
    这似乎在正常的本地情况下可以正常工作,但是当您需要为输入提供覆盖时就会出现问题。例如,在网络游戏中,客户端将触发输入,然后将目标发送到主服务器。然后,主服务器需要覆盖输入对象以使其接收到目标,然后调用效果。
    所以我想添加类似的东西
    void overrideInput(T);
    到 InputData 接口(interface),但因为它使用协方差,我不能使用泛型类型参数作为任何接口(interface)函数的参数。
    有没有办法绕过这个限制?这个概念看起来很简单:确保效果对象只与相同目标类型的输入对象匹配。当然,我可以用一堆不安全的 Actor 来蛮力完成这个,但似乎应该有更好的方法。

    最佳答案

    我通过添加另一种类型 Tinput 来编译您的代码。不知道是不是你想要的:

        public class AbilityData
    {
    List<InputData<Target,Target>> inputs;

    List<AbilityEffect> effects;

    public void exampleCreate()
    {
    BaseInputData<Tile,Target> input = new TileSelectData();
    inputs.Add(input);

    var effects = new List<AbilityEffect>();
    var effect = new BaseAbilityEffect<Tile,Target>(new TileEffect(), input);
    effects.Add(effect);
    }
    public void exampleRun()
    {
    foreach (InputData<AbilityInput, AbilityInput> input in inputs)
    {
    input.promptInput();
    }

    foreach (AbilityEffect effect in effects)
    {
    effect.execute();
    }
    }
    }
    public interface AbilityEffect
    {
    void execute();
    }

    public class BaseAbilityEffect<T,Tinput> : AbilityEffect
    where T : Target,Tinput
    {
    InputData<T,Tinput> input;

    TargetEffect<T> effect;

    public BaseAbilityEffect(TargetEffect<T> tEffect, InputData<T,Tinput> input)
    {
    this.input = input;
    this.effect = tEffect;
    }

    public void execute()
    {
    effect.execute(input.getInput());
    }
    }

    public class TargetEffect<T> where T : Target
    {
    public virtual void execute(T input) { }
    }

    public class UnitEffect : TargetEffect<Unit>
    {
    public override void execute(Unit unit)
    {
    // Do something on the unit
    }
    }

    public class TileEffect : TargetEffect<Tile>
    {
    public override void execute(Tile tile)
    {
    // Do something on the tile
    }
    }

    public interface InputData<out T,Tinput>
    where T: Tinput
    {
    void promptInput();

    T getInput();

    void overrideInput(Tinput input);
    }

    public class Target
    {
    }

    public class Tile : Target
    {
    }

    public class TileSelectData : BaseInputData<Tile,Target>
    {
    public TileSelectData()
    {
    }
    }

    public class Unit : Target
    {
    }

    public class AbilityInput
    {
    }

    public class BaseInputData<T,Tinput> : InputData<T,Tinput>
    where T:Tinput
    {
    public T getInput()
    {
    throw new NotImplementedException();
    }

    public void overrideInput(Tinput input)
    {
    throw new NotImplementedException();
    }

    public void promptInput()
    {
    throw new NotImplementedException();
    }
    }

    关于C# - 以类型安全的方式将输入对象映射到效果对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65107653/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com