我的任务是编写一个方法StringToType(),将字符串转换为指定的类型T.
但我不喜欢我实现方法StringToType()的方式。我想使用少于反射并尽可能确保性能。
请告知如何最好地实施/更改它。
class Program
{
static bool StringToType<T>(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<int>(intStr, ref val1);
Class1 c1;
res = StringToType<Class1>(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);
}
}
答案 0 :(得分:5)
这似乎对我来说是最好的。与各种消费者共同投入了一百万次。这是人们评论的结合,还有一些额外的。
static Boolean TryParseString<T>(
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 :(得分:1)
对于案例#1,它已经是最佳的。
对于案例#2,您可以使用Enum.Parse
并捕获ArgumentException
并返回false。
对于情况#3,方法FromString
是一个静态工厂方法,因此不包含在接口IConvertibleFromString
中(因此接口只是一个类型标记而不包含任何方法)或者它是一个变异this._value
或其他东西的实例方法,目前尚不清楚。如果是后者,那么只需将value
投射到IConvertibleFromString
并调用FromString
,就不需要反思。如果它是静态工厂方法,那么你必须使用反射。
答案 2 :(得分:0)
事物的当前结构不允许它是真正的StringToType,因为你不能调用FromString,因为你有一个“已经活动”的实例。调用FromString时,会创建并返回另一个实例 - 这意味着每次需要创建2个实例实例以实现所需的实例。
如果你想让它完美地运作,这是我的建议:
创建一个新类 - “StringActivator”(受Reflection的Activator启发)
创建一个Type方法 - StringActivator.CreateInstance(string ...)
激活字符串是一个由逗号分隔的/ xml字符串组成的字符串,其中每个项目都是构造函数参数。
在里面,查看类型(T)构造函数,找到具有所需参数数量的所有构造函数(在激活字符串中发送)。
现在,一旦你拥有了所有构造函数,尝试将你在激活字符串中发送的每个参数值转换为构造函数使用Recursion所期望的类型(调用StringActivator.CreateInstane,其中T是构造函数所期望的类型)
要使其工作,如果T是Primitive或ENum(Recursion的停止条件),则需要检查CreateInstance的开头,然后使用(T)转换。
当您转换所有逗号分隔的参数时,请使用Reflection.Emit为您发送的特定数量的参数创建编译调用。
将发出的函数委托映射到Type sent(),并在下次尝试从具有相同参数数量的字符串转换为T时调用它...
希望它有所帮助。