是否可以将两种类型的对象传递给 Restsharp?
Is it possible to pass 2 types of objects to Restsharp?
我们有这样的场景,外部 API return 用户 XML 或错误 XML 根据请求是成功还是失败。
目前我正在将用户 POCO 传递给 restsharp,并且工作正常。但如果失败,则此对象为 NULL。除非我们手动解析错误 XML,否则我们不会知道它失败的原因。
有没有办法解决这个问题?
例如
var restClient = new RestClient(baseURL);
var request = new RestRequest(uri);
request.Method = Method.POST;
var response = restClient.Execute<User>(request);
在执行上述方法时,API 可以 return 错误 xml 对象。如何在失败时获取错误对象并在成功时获取用户?
这是可以的,虽然代码有点难看。 RestSharp 允许您指定自己的 XML 反序列化器,因此我们需要这样做才能完成这项工作。
不过,首先,您需要一种可以存储 Error
或 User
的数据类型(我将其设为通用,因此它不仅适用于用户):
public class Result<T>
{
public T Data { get; set; }
public Error Error { get; set; }
}
所以想法是,现在当您执行请求时,您向 RestSharp 请求 Result<User>
而不仅仅是 User
,即:
var result = client.Execute<Result<User>>(request);
现在这是反序列化为 Error
或 User
所需的魔法。它是一个自定义反序列化器,继承自 RestSharp 的 XmlDeserializer
。警告:这段代码根本没有经过测试,但它有望为您指明正确的方向。
public class XmlResultDeserializer : XmlDeserializer
{
public override T Deserialize<T>(IRestResponse response)
{
if (!typeof(T).IsGenericType || typeof(T).GetGenericTypeDefinition() != typeof(Result<>))
return base.Deserialize<T>(response);
// Determine whether the response contains an error or normal data.
var doc = XDocument.Parse(response.Content);
var result = Activator.CreateInstance<T>();
if (doc.Root != null && doc.Root.Name == "Error")
{
// It's an error
var error = base.Deserialize<Error>(response);
var errorProperty = result.GetType().GetProperty("Error");
errorProperty.SetValue(result, error);
}
else
{
// It's just normal data
var innerType = typeof(T).GetGenericArguments()[0];
var deserializeMethod = typeof(XmlDeserializer)
.GetMethod("Deserialize", new[] { typeof(IRestResponse) })
.MakeGenericMethod(innerType);
var data = deserializeMethod.Invoke(this, new object[] { response });
var dataProperty = result.GetType().GetProperty("Data");
dataProperty.SetValue(result, data);
}
return result;
}
}
然后你会像这样连接它:
var restClient = new RestClient(baseURL);
client.AddHandler("application/xml", new XmlResultDeserializer());
var request = new RestRequest(uri);
request.Method = Method.POST;
var result = restClient.Execute<Result<User>>(request);
if (response.Data.Data != null)
{
var user = response.Data.Data;
// Do something with the user...
}
else if (response.Data.Error != null)
{
var error = response.Data.Error;
// Handle error...
}
我们有这样的场景,外部 API return 用户 XML 或错误 XML 根据请求是成功还是失败。
目前我正在将用户 POCO 传递给 restsharp,并且工作正常。但如果失败,则此对象为 NULL。除非我们手动解析错误 XML,否则我们不会知道它失败的原因。
有没有办法解决这个问题?
例如
var restClient = new RestClient(baseURL);
var request = new RestRequest(uri);
request.Method = Method.POST;
var response = restClient.Execute<User>(request);
在执行上述方法时,API 可以 return 错误 xml 对象。如何在失败时获取错误对象并在成功时获取用户?
这是可以的,虽然代码有点难看。 RestSharp 允许您指定自己的 XML 反序列化器,因此我们需要这样做才能完成这项工作。
不过,首先,您需要一种可以存储 Error
或 User
的数据类型(我将其设为通用,因此它不仅适用于用户):
public class Result<T>
{
public T Data { get; set; }
public Error Error { get; set; }
}
所以想法是,现在当您执行请求时,您向 RestSharp 请求 Result<User>
而不仅仅是 User
,即:
var result = client.Execute<Result<User>>(request);
现在这是反序列化为 Error
或 User
所需的魔法。它是一个自定义反序列化器,继承自 RestSharp 的 XmlDeserializer
。警告:这段代码根本没有经过测试,但它有望为您指明正确的方向。
public class XmlResultDeserializer : XmlDeserializer
{
public override T Deserialize<T>(IRestResponse response)
{
if (!typeof(T).IsGenericType || typeof(T).GetGenericTypeDefinition() != typeof(Result<>))
return base.Deserialize<T>(response);
// Determine whether the response contains an error or normal data.
var doc = XDocument.Parse(response.Content);
var result = Activator.CreateInstance<T>();
if (doc.Root != null && doc.Root.Name == "Error")
{
// It's an error
var error = base.Deserialize<Error>(response);
var errorProperty = result.GetType().GetProperty("Error");
errorProperty.SetValue(result, error);
}
else
{
// It's just normal data
var innerType = typeof(T).GetGenericArguments()[0];
var deserializeMethod = typeof(XmlDeserializer)
.GetMethod("Deserialize", new[] { typeof(IRestResponse) })
.MakeGenericMethod(innerType);
var data = deserializeMethod.Invoke(this, new object[] { response });
var dataProperty = result.GetType().GetProperty("Data");
dataProperty.SetValue(result, data);
}
return result;
}
}
然后你会像这样连接它:
var restClient = new RestClient(baseURL);
client.AddHandler("application/xml", new XmlResultDeserializer());
var request = new RestRequest(uri);
request.Method = Method.POST;
var result = restClient.Execute<Result<User>>(request);
if (response.Data.Data != null)
{
var user = response.Data.Data;
// Do something with the user...
}
else if (response.Data.Error != null)
{
var error = response.Data.Error;
// Handle error...
}