とにかくカスタムルールを使用したいと思われるので、登録して後で活用するカスタムパーサーのリストを作成します。
public static class StringParsers
{
private static Dictionary<Type, object> Parsers = new Dictionary<Type, object>();
public static void RegisterParser<T>(Func<string, T> parseFunction)
{
Parsers[typeof(T)] = parseFunction;
}
public static T Parse<T>(string input)
{
object untypedParser;
if (!Parsers.TryGetValue(typeof(T), out untypedParser))
throw new Exception("Could not find a parser for type " + typeof(T).FullName);
Func<string, T> parser = (Func<string, T>)untypedParser;
return parser(input);
}
}
アプリケーションの初期化中に、後で使用する予定の型をアプリケーションに登録します(ジェネリックスを使用しているため、これは既知であると思います)。
StringParsers.RegisterParser<string[]>(input => input.Split(','));
StringParsers.RegisterParser<int[]>(input => input.Split(',').Select(i => Int32.Parse(i)).ToArray());
StringParsers.RegisterParser<int>(input => Int32.Parse(input));
最後に、あなたはそれを簡単に呼ぶことができます:
string testArrayInput = "1,2,8";
int[] integers = StringParsers.Parse<int[]>(testArrayInput); // {1, 2, 8}
string[] strings = StringParsers.Parse<string[]>(testArrayInput); // {"1", "2", "8"}
int singleInt = StringParsers.Parse<int>("9999"); //9999
さて、これは非常に単純な実装です。Func<string, T>
タイプを使用する代わりにインターフェイスを使用し、IStringParser
必要に応じて解析のより深い実装を提供できるように、拡張することをお勧めします。さらに、スレッドセーフにすることもできます(問題が発生しないことが確実な場合、または起動時の登録が使用前であることが確実な場合を除く)
編集:本当に、本当に、本当にすべてを1つの関数にまとめて、コンマ区切りの配列を考慮したい場合は、次を使用できます。
public static T Str2Val<T>(string str)
{
if (!typeof(T).IsArray)
return (T)Convert.ChangeType(str, typeof(T));
Type elementType = typeof(T).GetElementType();
string[] entries = str.Split(',');
int numberOfEntries = entries.Length;
System.Array array = Array.CreateInstance(elementType, numberOfEntries);
for(int i = 0; i < numberOfEntries; i++)
array.SetValue(Convert.ChangeType(entries[i], elementType), i);
return (T)(object)array;
}
しかし、これはとても間違っていると感じます。アレクサンダーの答えに二重の一般的な入力を避けるためのより良い方法があるはずですが、そこに行きます。