c# - 在 C# 中为原始类型创建包装器的最佳方法是什么?
问题描述
我正在尝试制作一个使用终端/外壳与(几乎)一切交互的游戏(使用 Unity 3D 引擎)。这也是很多问题出现的地方,因为实现必须同时是刚性的、灵活的、简单的和可扩展的。
目前我对终端的美学并不感兴趣——只是 shell 的功能——因此我专注于创建一个命令类型,该类型可以从被解析为通用参数类型的字符串实例化然后转换为内部类型(如string
,int
等)。
下面,我提供了一个Command
类的代码。我正在努力工作,但我一直试图将其解析为最终可以执行的一些动作。问题是班级ArgumentType
内部Argument
不想被强制转换,我没有找到任何好的解决方案。谁能帮我解决这个问题或给我一个工作方向?先感谢您!
namespace Terminal.Shells
{
public abstract class Command
{
private readonly Action<ArgumentType []> procedure;
private readonly CommandManual manual;
public IEnumerable<Type> Parse (string line)
{
for (int i = 0; i < manual.RequiredArguments.Length; i++)
{
var word = EatNextWord (ref line);
if (string.IsNullOrEmpty (word))
throw new System.Exception (); // TODO: index out of range
var argumentType = manual.RequiredArguments [i].Type;
// ### conversion from string to type
}
// TODO: Optional Arguments
}
public string EatNextWord (ref string line) { /* ... */ }
}
}
该类CommandManual
仅包含两个有趣的属性:
internal readonly Argument [] RequiredArguments;
internal readonly Argument [] OptionalArguments;
Argument
班级:
namespace Terminal.Shells
{
public struct Argument
{
private readonly string identifier;
private readonly ArgumentType type;
public string Identifier => this.identifier;
public ArgumentType Type => this.type;
// ...
}
}
我创建了ArgumentType
and ArgumentType<T>
:第一个类似于一个Enumeration
类,可以在任何地方使用,后者用于从输入(字符串)到关联类型的实际转换。
namespace Terminal.Shells
{
public abstract partial class ArgumentType : Enumeration
{
public static readonly ArgumentType Command = new CommandType ();
public static readonly ArgumentType Boolean = new BooleanType ();
public static readonly ArgumentType String = new StringType ();
public static readonly ArgumentType Range = new RangeType ();
protected ArgumentType (string name, int value)
: base (name, value) { }
// ### THIS GOES WRONG
public ArgumentType<T> GenericType => ???;
}
public abstract partial class ArgumentType<T> : ArgumentType
{
protected ArgumentType (string name, int value)
: base (name, value) { }
/// <summary>
/// Tries to cast the value of an argument in this wrapper
/// to an actual primitive value enclosed in a <see cref="Maybe{T}"/>.
/// </summary>
/// <returns>A <see cref="Maybe{T}"/> value that might contain the
/// casted value.</returns>
public abstract Maybe<T> TryCast (string input);
/// <summary>
/// Casts the value of an argument in this wrapper to
/// an actual primitive value or throws an error.
/// </summary>
/// <returns>An <see cref="Either{T, ArgumentTypeException}"/> value
/// that contains the casted value or an <see cref="ArgumentTypeException"/>.
/// </returns>
public virtual Either<T, ArgumentTypeException> Cast (string input)
{
return this
.TryCast (input)
.ValueOr (new ArgumentTypeException (
typeof (T),
typeof (void)
));
}
}
}
这种通用枚举类型的实例之一是IntegerType
类:
namespace Terminal.Shells
{
public class IntegerType : ArgumentType<int>
{
public IntegerType () : base ("integer", 4) { }
/// <inheritdoc/>
public override Maybe<int> TryCast (string input)
{
int.TryParse (input, out var result);
return result;
}
}
}
解决方案
推荐阅读
- r - R Jupyter Notebook 中的非零退出状态,但不在 R 中
- python-3.x - Discord.py 按需运行异步函数
- javascript - 当值为空时删除 ChartJS 中的空格
- javascript - Async api fetch with redux thunk
- html - 以 HTML 格式将文件复制到剪贴板
- linux - 用于根据文件类型将文件夹移动到相应文件夹的 Shell 脚本
- javascript - Electron - fs.readdir 回调有时不会在重新加载时执行
- android - Firestore Recycler 在一个页面(实例)中加载,但不在另一个页面中
- apache - 告诉浏览器不再指向 https,而是现在指向 http
- clickonce - 桌面应用程序用户能否从位于 LAN 服务器上的 CNG 密钥库中检索密钥