类型可以解析字符串的通用类

时间:2018-02-02 11:33:17

标签: c# generics where-clause

我想创建一个泛型类,其中类的类型可以解析字符串。

我想将这个类用于任何具有静态函数Parse(string)的类, 像System.Int32,System.Double,但也适用于像System.Guid这样的类。它们都具有静态Parse函数

所以我的类需要一个where子句,它将我的泛型类型约束为具有Parse函数的类型

我想像这样使用它:

class MyGenericClass<T> : where T : ??? what to do ???
{
     private List<T> addedItems = new List<T>()

     public void Add(T item)
     {
          this.AddedItems.Add(item);
     }

     public void Add(string itemAsTxt) 
     {
         T item = T.Parse(itemAsTxt);
         this.Add(item);
     }
}

在where子句中写什么?

3 个答案:

答案 0 :(得分:5)

我对使用反射进行解析的答案感到不满意。

我更喜欢类型安全的解决方案,因此编译器会抱怨缺少Parse函数。

通常,您会约束到具有接口的类。但正如其他人所说,没有共同的界面。想一想我不需要接口,我需要一个可以调用的功能

所以我的解决方案是坚持创建者会向Parse函数提供一个委托,该委托将解析字符串以键入T

class MyGenericClass<T>
{
    public MyGenericClass(Func<string, T> parseFunc)
    {
         this.parseFunc = parseFunc;
    }

    private readonly Func<string, T> parseFunc;

    public void Add(string txt) 
    {
        this.Add(parseFunc(txt));
    }
}

用法:

MyGenericClass<Guid> x = new MyGenericClass<Guid>(txt => Guid.Parse(txt));
MyGenericClass<int> y = new MyGenericClass<int> (txt => System.Int32.Parse(txt));

答案比我想象的要简单

答案 1 :(得分:1)

我可能会误解你的问题,但是这会解决这个问题吗?

    static void Main(string[] args)
    {
        Guid g = DoParse<Guid>("33531071-c52b-48f5-b0e4-ea3c554b8d23");

    }

    public static T DoParse<T>(string value) 
    {
        T result = default(T);
        MethodInfo methodInfo = typeof(T).GetMethod("Parse");
        if (methodInfo != null)
        {

            ParameterInfo[] parameters = methodInfo.GetParameters();
            object classInstance = Activator.CreateInstance(typeof(T), null);

            object[] parametersArray = new object[] { value };
            result = (T)methodInfo.Invoke(methodInfo, parametersArray);

        }
        return result;
    }

答案 2 :(得分:0)

你根本无法在编译时这样做。除了名字之外,所有这些方法都没有任何。它们既不在任何公共接口中定义,也不具有相同的参数。

想象一下,你有自己的方法,意外地有这个名字,但做了一些完全不同的事情。另外它也是一个实例方法:

class MyType
{
    void Parse() { ... }
}

正如您所看到的那样,该方法甚至没有任何参数,因此很难找到 - 例如 - int.Parse(myString)and myInstanceOfMyType.Parse之间的任何公共逻辑()`。

但即使如果你也能做到。你会对item做什么?他们之间没有什么共同之处。特别是调用 the methpd是不可能的,因为它们完全不同。

您可以在运行时使用类似的方法循环所有类型:

var types = allAssemblies.SelectMany(x => x.GetTypes())
                .Where(x => x.GetMethod("Parse") != null);

但请注意,如果每个类型存在多个带​​有名称的方法,则会产生AmbiguousMatchException,这是方法重载的时候。