字符串的通用generics类型转换
我的任务是编写一个StringToType()方法,将字符串转换为指定的类型T.
- 对于基本类型,我使用Convert.ChangeType()方法
- 对于枚举类型 – Enum.TryParse()
- 对于所有其他自定义类型,我创建了一个接口“IConvertibleFromString”,其中包含一个方法“FromString()”,将字符串转换为指定的类型。 任何需要从字符串转换的类都必须实现此接口。
但我不喜欢我实现方法StringToType()的方式。 我想使用少于reflection并尽可能确保性能。
请告知如何最好地实施/更改它。
class Program { static bool StringToType(string str, ref T value) { Type typeT = typeof(T); bool isSuccess = false; if (typeT.GetInterface("IConvertibleFromString") != null) { return (bool)typeT.GetMethod("FromString").Invoke(value, new object[] { str }); } else if (typeT.IsEnum) { MethodInfo methodTryParse = typeT.GetMethod("TryParse").MakeGenericMethod(typeT); return (bool)methodTryParse.Invoke(null, new object[] { str, value }); } else if (typeT.IsPrimitive) { value = (T)Convert.ChangeType(str, typeT); return true; } return isSuccess; } static void Main(string[] args) { string intStr = "23"; int val1 = 0; bool res = StringToType(intStr, ref val1); Class1 c1; res = StringToType(intStr, ref c1); Console.ReadKey(); } } interface IConvertibleFromString { bool FromString(string str); } class MySomeClass : IConvertibleFromString { int someVal; public bool FromString(string str) { return int.TryParse(str, out someVal); } }
这似乎对我来说是最好的。 与各种消费者共同投入了一百万次。 这是人们评论的结合,还有一些额外的评论。
static Boolean TryParseString( String stringValue, ref T value) { Type typeT = typeof(T); if (typeT.IsPrimitive) { value = (T)Convert.ChangeType(stringValue, typeT); return true; } else if (typeT.IsEnum) { value = (T)System.Enum.Parse(typeT, stringValue); // Yeah, we're making an assumption return true; } else { var convertible = value as IConvertible; if (convertible != null) { return convertible.FromString(stringValue); } } return false; }
对于案例#1,它已经是最佳的。
对于情况#2,您可以使用Enum.Parse
并捕获ArgumentException
并返回false。
对于情况#3方法, FromString
是一个静态工厂方法,因此不包含在接口IConvertibleFromString
(所以接口只是一个类型标记并且不包含任何方法)或者它是一个实例方法,它会改变this._value
或者其他东西,它是不清楚。 如果是后者,那么只需将value
IConvertibleFromString
为IConvertibleFromString
并调用FromString
,就不需要reflection。 如果它是静态工厂方法,那么你必须使用reflection。
事物的当前结构不允许它是真正的StringToType,因为你不能调用FromString,因为你有一个“已经活动”的实例。 调用FromString时,会创建并返回另一个实例 – 这意味着每次需要创建2个实例实例以实现所需的实例。
如果你想要它完美地工作,这是我的建议:
-
创建一个新类 – “StringActivator”(灵感来自Reflection的Activator)
-
创建一个Type方法 – StringActivator.CreateInstance(string …)
-
激活字符串是一个由逗号分隔/ xml字符串组成的字符串,其中每个项都是构造函数参数。
-
在里面,遍历类型(T)构造函数并查找具有所请求参数数量的所有构造函数(在激活字符串中发送)。
-
现在,一旦你拥有了所有构造函数,尝试将你在激活字符串中发送的每个参数值转换为构造函数使用Recursion所期望的类型(调用StringActivator.CreateInstane,其中T是构造函数所期望的类型)。
为此,如果T是Primitive或ENum(递归的停止条件),则需要检查CreateInstance的开头,然后使用(T)转换。
-
当您转换所有逗号分隔的参数时,请使用Reflection.Emit为您发送的特定数量的参数创建编译调用。
-
将发出的函数委托映射到Type sent(),并在下次尝试从具有相同参数数量的字符串转换为T时调用它…
希望能帮助到你。