C# 字符串的通用泛型类型转换

C# 字符串的通用泛型类型转换,c#,generics,type-conversion,C#,Generics,Type Conversion,我的任务是编写一个方法StringToType(),将字符串转换为指定的类型T 对于基元类型,我使用Convert.ChangeType()方法 对于枚举类型-enum.TryParse() 对于所有其他自定义类型,我创建了一个接口“IConvertibleFromString”,其中包含一个方法“FromString()”,用于将字符串转换为指定类型。任何需要从字符串转换的类都必须实现此接口 但是我不喜欢我实现方法StringToType()的方式。我希望使用较少的反射,并尽可能确保性能 请告

我的任务是编写一个方法StringToType(),将字符串转换为指定的类型T

  • 对于基元类型,我使用Convert.ChangeType()方法
  • 对于枚举类型-enum.TryParse()
  • 对于所有其他自定义类型,我创建了一个接口“IConvertibleFromString”,其中包含一个方法“FromString()”,用于将字符串转换为指定类型。任何需要从字符串转换的类都必须实现此接口
  • 但是我不喜欢我实现方法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);
        }
    }
    
    类程序
    {
    静态bool StringToType(字符串str,ref T值)
    {
    类型T=类型(T);
    bool isSuccess=错误;
    if(typeT.GetInterface(“IConvertibleFromString”)!=null)
    {
    return(bool)typeT.GetMethod(“FromString”).Invoke(值,新对象[]{str});
    }
    else if(输入IsEnum)
    {
    MethodInfo methodTryParse=typeT.GetMethod(“TryParse”).MakeGenericMethod(typeT);
    return(bool)methodrParse.Invoke(null,新对象[]{str,value});
    }
    else if(类型为IsPrimitive)
    {
    value=(T)Convert.ChangeType(str,typeT);
    返回true;
    }
    返回成功;
    }
    静态void Main(字符串[]参数)
    {
    字符串intStr=“23”;
    int val1=0;
    bool res=StringToType(intStr,ref val1);
    1类c1;
    res=StringToType(intStr,参考c1);
    Console.ReadKey();
    }
    }
    接口IConvertibleFromString
    {
    bool-FromString(stringstr);
    }
    类MySomeClass:IConvertibleFromString
    {
    int-someVal;
    公共bool FromString(string str)
    {
    返回int.TryParse(str,out someVal);
    }
    }
    
    这对我来说似乎是最好的。对不同的消费者进行了一百万次迭代。这是一个结合了人们的意见,有一点额外的

        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;
    
        }
    
    static Boolean TryParseString(
    字符串字符串值,参考T值)
    {
    类型T=类型(T);
    如果(类型为IsPrimitive)
    {
    value=(T)Convert.ChangeType(stringValue,typeT);
    返回true;
    }
    else if(输入IsEnum)
    {
    value=(T)System.Enum.Parse(typeT,stringValue);//是的,我们正在做一个假设
    返回true;
    }
    其他的
    {
    var可转换=作为IConvertible的值;
    如果(可转换!=null)
    {
    返回可转换的.FromString(stringValue);
    }
    }
    返回false;
    }
    
    对于案例1,它已经是最优的

    对于案例2,您可以使用
    Enum.Parse
    并捕获
    ArgumentException
    并返回false


    例如#3 method
    FromString
    要么是一个静态工厂方法,因此不包含在接口
    IConvertibleFromString
    中(因此该接口只是一个类型标记,不包含任何方法),要么是一个实例方法,它变异了
    。_value
    或其他什么,它不清楚。如果是后者,则只需将
    强制转换为
    IConvertibleFromString
    并调用
    FromString
    ,无需反射。如果是静态工厂方法,则必须使用反射。

    当前的结构不允许它是真正的StringToType,因为在拥有“已激活”实例之前,不能调用FromString。调用FromString时,将创建并返回另一个实例-这意味着您每次需要创建2个实例来实现所需的功能

    如果你想让它完美运行,我的建议是:

  • 创建一个新类-“StringActivator”(受反射的Activator启发)

  • 创建类型为-StringActivator.CreateInstance(字符串…)的方法

  • 激活字符串是由逗号分隔的/xml字符串组成的字符串,其中每个项都是构造函数参数

  • 在内部,检查类型(T)构造函数并找到所有具有请求数量的参数(在激活字符串中发送)的构造函数

  • 现在,拥有所有构造函数后,尝试使用递归将激活字符串中发送的每个参数值转换为构造函数期望的类型(调用StringActivator.CreateInstane,其中T是构造函数期望的类型)

  • 要使其正常工作,您需要在CreateInstance的开头检查T是原语还是枚举(递归的停止条件),然后使用(T)Convert

  • 转换所有以逗号分隔的参数时,请使用Reflection.Emit为所发送的参数和特定数量的参数创建编译调用

  • 将发出的函数的委托映射到sent()类型,并在下次尝试从具有相同参数数的字符串转换为T时调用它


  • 希望有帮助。

    一个简单的优化方法是以最便宜的顺序检查布尔条件(假设GetInterface()的效率最低),而不是执行
    if(typeT.GetInterface(“IConvertibleFromString”)!=null){return(bool)typeT.GetMethod(“FromString”).Invoke(value,new object[]{str};}
    您可以执行
    var iface=value作为IConvertibleFromString;如果(iface!=null)返回iface.FromString(str)。那会帮你省下反思的惩罚嗯<代码>IConvertible.FromString()
    ?你从哪儿弄来的?