泛型,用于在C#中将WebRequest和解析概括为自定义对象
本文关键字:对象 自定义 和解 WebRequest 用于 中将 泛型 | 更新日期: 2023-09-27 17:59:59
一个架构问题。我用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
或WorkFlow。
在解析之前,这项工作编译得相当好。以前我这样分析它:
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>'
如果所有类都有一个公共的无参数构造函数,则可以将约束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;
}
如果您无法确保所有类都有一个公共的无参数构造函数,那么您将不得不求助于工厂来创建对象。
您需要为泛型方法指定一个约束,以便生成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(){
[...]
}