0

有点建筑问题。我在 C# (Mono) 中做了很多 WebRequest:s。下面是一个如何声明获取“WorkFlowSchemes”的方法的示例:

public void GetWorkFlowSchemes(
   Credientials credentials, 
   ServerDelegates.WorkFlowSchemesSuccessDelegate successDelegate, 
   ServerDelegates.ErrorDelegate errorDelegate)

然后哪个具有“硬编码”值,用于从哪个 url 获取,哪个回调它调用的响应以及在该回调中:要解析的类型。

我想让这个方法通用,不必为我所做的每种类型的调用编写 X 个非常相似的方法。相反,我想要这样的东西:

public void GetCustomPath<K>(
    Credientials credentials,
    Path pathToFetch,
    ServerDelegate<K>.SuccessDelegate successDelegate, //Generic delegate to return different types of parsed result
    ServerDelegates.ErrorDelegate errorDelegate) // no need to be generic

其中 K 是要返回的委托的类型,即工作流WorkFlowScemes

在解析之前,这项工作编译得相当好。以前我通过这样做来解析它:

List<WorkFlowScheme> workFlowSchemeList = serverXmlParser.parseXmlToWorkFlowSchemeList(responseBody);

WorkFlowList 的另一种硬编码解析方法我更愿意概括。parseXmlToWorkFlowSchemeList看起来像这样:

    public List<WorkFlowScheme> parseXmlToWorkFlowSchemeList (string xml)
    {
        XDocument doc = XDocument.Parse(xml);
        List<WorkFlowScheme> result = 
            (
                from x in doc.Element("workflowschemeList").Elements("workflowscheme")
                select new WorkFlowScheme().Setup(x)
                ).ToList();
        return result;
    }

where .Setup(x)是存储在每种类型中的帮助方法,用于将 XElement 值转换并存储为当前对象中的字符串。这是我卡住的地方。首先,我尝试制作一个通用方法:

public List<T> parseXmlToCustomObject<T> (string xml, String root, String key)
{
        XDocument doc = XDocument.Parse(xml);
        List<T> result = 
            (
                from x in doc.Element(root).Elements(key)
                select new T().Setup(x)
                ).ToList();
        return result;
}

“选择新的 T.Setup(x)”不起作用

  • 首先,因为我无法创建“ new T()”(编辑:已经解决)
  • 其次导致编译器不知道在哪里可以找到 Setup 方法

有什么建议么?

我还考虑过让我的所有对象解析为“ServerObject”的子类,以便更容易调用.Setup,但不知道如何将其与泛型合并。

编辑:这是我到目前为止得到的:

public void GetCustomListObject<T>(Account account, String path, RequestStateGen<List<T>>.SuccessDelegate successDelegate, ServerDelegates.ErrorDelegate errorDelegate)
        where T : ServerObject, new()
    {
        var request = getGetRequest(account, path);

        RequestStateGen<List<T>> state = new RequestStateGen<List<T>>();
        state.Request = request;

        IAsyncResult result =
            request.BeginGetResponse(new AsyncCallback(onGetWorkFlowSchemes), state);

        //setupTimeOut(result, state);
        string responseBody = extractResponseAndCallDelegateOnError(request, result, errorDelegate);
        if (responseBody != null)
        {
            List<T> parsedObject = serverXmlParser.parseXmlToCustomObject<T>(responseBody);
            if (parsedObject != null)
            {
                successDelegate(parsedObject);
            }
        }
    }

及解析方法:

public List<T> parseXmlToCustomObject<T> (string xml)
        where T : ServerObject, new()
    {
        XDocument doc = XDocument.Parse(xml);
        List<T> result = 
            (
                from x in doc.Element("workflowschemeList").Elements("workflowscheme")
                select new T().Setup(x)
                ).ToList();
        return result;
    }

其中 ServerObject 是我所有包含 .Setup 的自定义对象类的基础对象。我现在得到的错误是在“List result =”线上,但有错误:

Cannot implicitly convert type `System.Collections.Generic.List<xxxx.Core.Network.Objects.ServerObject>' to `System.Collections.Generic.List<T>'
4

2 回答 2

4

如果您的所有类都有公共无参数构造函数,则可以将约束添加where T : new()parseXmlToCustomObject. 这将摆脱第一个错误。

要摆脱第二个错误,您将必须创建一个包含该Setup方法的接口或基类,并使您的所有类都实现此接口或从该基类派生并将其添加为另一个约束:where T : ISetupable, new(). (请原谅名字)

您的方法将如下所示:

public List<T> parseXmlToCustomObject<T> (string xml, String root, String key)
    where T : ISetupable, new()
{
        XDocument doc = XDocument.Parse(xml);
        List<T> result = 
            (
                from x in doc.Element(root).Elements(key)
                select new T().Setup(x)
                ).ToList();
        return result;
}

如果您无法确保所有类都有一个公共的无参数构造函数,您将不得不求助于工厂来创建您的对象。

于 2013-02-19T09:57:51.750 回答
2

您需要为泛型方法指定一个约束,以便创建一个新的实例T

public List<T> parseXmlToCustomObject<T> (string xml, String root, String key) where T : new(){
[...]
}

[编辑] 您的第二个问题:您需要有一个基类或接口,该基类或接口具有该Setup()方法和对您的泛型方法的另一个约束:

假设您有一个BaseClass具有您的Setup()方法的基类:

public List<T> parseXmlToCustomObject<T> (string xml, String root, String key) where T : BaseClass, new(){
[...]
}
于 2013-02-19T09:58:52.877 回答