如何指定C#泛型类型必须支持Parse(string)?

如何指定C#泛型类型必须支持Parse(string)?,c#,generics,C#,Generics,我试图为包含SQL查询结果的XML字符串创建一个解析器框架。其目的是从泛型类继承,泛型类用列数据类型实例化。包含的代码适用于单列类型。将有两列的附加类等 我需要能够指定泛型类型必须支持Parse(string)方法。我该怎么做 abstract class OneColumnParser<Col1> { abstract string Column1; List<Col1> ParseQueryResult(string queryResult)

我试图为包含SQL查询结果的XML字符串创建一个解析器框架。其目的是从泛型类继承,泛型类用列数据类型实例化。包含的代码适用于单列类型。将有两列的附加类等

我需要能够指定泛型类型必须支持Parse(string)方法。我该怎么做

abstract class OneColumnParser<Col1>
{
    abstract string Column1;

    List<Col1> ParseQueryResult(string queryResult)
    {
        XmlDocument xDoc = new XmlDocument();
        xDoc.LoadXml(queryResult);
        List<Col1> results = new List<Col1>();

        foreach (XmlNode xNode in xDoc.GetElementsByTagName(Column1))
        {
            results.Add(Col1.Parse(xNode.InnerText));
        }
    }
}
抽象类语法分析器
{
抽象字符串列1;
列表ParseQueryResult(字符串queryResult)
{
XmlDocument xDoc=新的XmlDocument();
LoadXml(queryResult);
列表结果=新列表();
foreach(xDoc.GetElementsByTagName(Column1)中的XmlNode xNode)
{
Add(Col1.Parse(xNode.InnerText));
}
}
}

当我编译上面的代码时,我在results.Add()行上得到“'Col1'是一个'type参数',它在给定上下文中无效”,因为我没有指定类型必须支持该方法。但是怎么做呢?

一种方法是为
Col1
类型定义无参数构造函数和接口:

interface IParseable
{
    void Parse(string text);
}

abstract class OneColumnParser<T> where T : IParseable, new
{
    abstract string Column1;

    List<T> ParseQueryResult<T>(string queryResult)
    {
        XmlDocument xDoc = new XmlDocument();
        xDoc.LoadXml(queryResult);
        var results = new List<T>();

        foreach (XmlNode xNode in xDoc.GetElementsByTagName(Column1))
        {
            var col = new T();
            col.Parse(xNode.InnerText);
            results.Add(col);
        }
    }
}
接口IParseable
{
void解析(字符串文本);
}
抽象类OneColumnParser,其中T:IParseable,new
{
抽象字符串列1;
列表ParseQueryResult(字符串queryResult)
{
XmlDocument xDoc=新的XmlDocument();
LoadXml(queryResult);
var results=新列表();
foreach(xDoc.GetElementsByTagName(Column1)中的XmlNode xNode)
{
var col=新的T();
col.Parse(xNode.InnerText);
结果:添加(col);
}
}
}

一种方法是为
Col1
类型定义无参数构造函数和接口:

interface IParseable
{
    void Parse(string text);
}

abstract class OneColumnParser<T> where T : IParseable, new
{
    abstract string Column1;

    List<T> ParseQueryResult<T>(string queryResult)
    {
        XmlDocument xDoc = new XmlDocument();
        xDoc.LoadXml(queryResult);
        var results = new List<T>();

        foreach (XmlNode xNode in xDoc.GetElementsByTagName(Column1))
        {
            var col = new T();
            col.Parse(xNode.InnerText);
            results.Add(col);
        }
    }
}
接口IParseable
{
void解析(字符串文本);
}
抽象类OneColumnParser,其中T:IParseable,new
{
抽象字符串列1;
列表ParseQueryResult(字符串queryResult)
{
XmlDocument xDoc=新的XmlDocument();
LoadXml(queryResult);
var results=新列表();
foreach(xDoc.GetElementsByTagName(Column1)中的XmlNode xNode)
{
var col=新的T();
col.Parse(xNode.InnerText);
结果:添加(col);
}
}
}

也许这会有所帮助。当您声明泛型函数时,您可以指定泛型函数必须实现interafce。通过这个接口,您可以设置Parse()支持。例如:

public void SomeFunction<T>(T variable) where T : IDisposable
       {
           variable.Dispose();
       }
public void SomeFunction(T变量),其中T:IDisposable
{
变量Dispose();
}

也许这会有所帮助。当您声明泛型函数时,您可以指定泛型函数必须实现interafce。通过这个接口,您可以设置Parse()支持。例如:

public void SomeFunction<T>(T variable) where T : IDisposable
       {
           variable.Dispose();
       }
public void SomeFunction(T变量),其中T:IDisposable
{
变量Dispose();
}

因为接口不能有静态方法,所以不能(直接)按要求执行。反射是解决问题的一种方法,但它只在运行时验证,而不是由编译器强制执行。例如

abstract class OneColumnParser<TCol>
{
    private static MethodInfo ParseInfo = typeof(TCol).GetMethod("Parse", BindingFlags.Public | BindingFlags.Static, null, new[] { typeof(string) }, null);
    abstract string Column1;

    static OneColumnParser()
    {
        if (typeof(TCol) != typeof(string) && (ParseInfo == null || !typeof(TCol).IsAssignableFrom(ParseInfo.ReturnType)))
            throw new InvalidOperationException("Invalid type, must contain public static TCol Parse(string)");
    }

    private static TCol Parse(string value)
    {
        if (typeof(TCol) == typeof(string))
            return (TCol)(object)value;
        else
            return (TCol)ParseInfo.Invoke(null, new[] { value });
    }

    public List<TCol> ParseQueryResult(string queryResult)
    {
        XmlDocument xDoc = new XmlDocument();
        xDoc.LoadXml(queryResult);
        List<TCol> results = new List<TCol>();

        foreach (XmlNode xNode in xDoc.GetElementsByTagName(Column1))
        {
            results.Add(Parse(xNode.InnerText));
        }

        return results;
    }
}
抽象类语法分析器
{
私有静态MethodInfo ParseInfo=typeof(TCol).GetMethod(“Parse”,BindingFlags.Public | BindingFlags.static,null,new[]{typeof(string)},null);
抽象字符串列1;
静态OneColumnParser()
{
if(typeof(TCol)!=typeof(string)&(ParseInfo==null | |!typeof(TCol).IsAssignableFrom(ParseInfo.ReturnType)))
抛出新的InvalidOperationException(“无效类型,必须包含公共静态TCol解析(字符串)”);
}
私有静态TCol解析(字符串值)
{
if(typeof(TCol)=typeof(string))
返回(TCol)(对象)值;
其他的
return(TCol)ParseInfo.Invoke(null,new[]{value});
}
公共列表ParseQueryResult(字符串queryResult)
{
XmlDocument xDoc=新的XmlDocument();
LoadXml(queryResult);
列表结果=新列表();
foreach(xDoc.GetElementsByTagName(Column1)中的XmlNode xNode)
{
Add(Parse(xNode.InnerText));
}
返回结果;
}
}

与定义自己的接口不同,这将使用
Parse
方法处理现有类型,例如
int
DateTime
更新添加了代码,这样它也可以在
字符串上工作。

因为接口不能有静态方法,所以不能(直接)按要求执行。反射是解决问题的一种方法,但它只在运行时验证,而不是由编译器强制执行。例如

abstract class OneColumnParser<TCol>
{
    private static MethodInfo ParseInfo = typeof(TCol).GetMethod("Parse", BindingFlags.Public | BindingFlags.Static, null, new[] { typeof(string) }, null);
    abstract string Column1;

    static OneColumnParser()
    {
        if (typeof(TCol) != typeof(string) && (ParseInfo == null || !typeof(TCol).IsAssignableFrom(ParseInfo.ReturnType)))
            throw new InvalidOperationException("Invalid type, must contain public static TCol Parse(string)");
    }

    private static TCol Parse(string value)
    {
        if (typeof(TCol) == typeof(string))
            return (TCol)(object)value;
        else
            return (TCol)ParseInfo.Invoke(null, new[] { value });
    }

    public List<TCol> ParseQueryResult(string queryResult)
    {
        XmlDocument xDoc = new XmlDocument();
        xDoc.LoadXml(queryResult);
        List<TCol> results = new List<TCol>();

        foreach (XmlNode xNode in xDoc.GetElementsByTagName(Column1))
        {
            results.Add(Parse(xNode.InnerText));
        }

        return results;
    }
}
抽象类语法分析器
{
私有静态MethodInfo ParseInfo=typeof(TCol).GetMethod(“Parse”,BindingFlags.Public | BindingFlags.static,null,new[]{typeof(string)},null);
抽象字符串列1;
静态OneColumnParser()
{
if(typeof(TCol)!=typeof(string)&(ParseInfo==null | |!typeof(TCol).IsAssignableFrom(ParseInfo.ReturnType)))
抛出新的InvalidOperationException(“无效类型,必须包含公共静态TCol解析(字符串)”);
}
私有静态TCol解析(字符串值)
{
if(typeof(TCol)=typeof(string))
返回(TCol)(对象)值;
其他的
return(TCol)ParseInfo.Invoke(null,new[]{value});
}
公共列表ParseQueryResult(字符串queryResult)
{
XmlDocument xDoc=新的XmlDocument();
LoadXml(queryResult);
列表结果=新列表();
foreach(xDoc.GetElementsByTagName(Column1)中的XmlNode xNode)
{
Add(Parse(xNode.InnerText));
}
返回结果;
}
}
与定义自己的接口不同,这将使用
Parse
方法处理现有类型,例如
int
DateTime
更新添加了代码,以便在
strin上工作