是否可以将两种类型的对象传递给Restsharp?

Nil*_*Pun 6 c# restsharp deserialization

我们有这样的场景:外部API根据请求是成功还是失败返回User XML或Error XML.

目前我正在将用户POCO传递给restsharp并正常工作.但如果失败,则此对象为NULL.除非我们手动解析Error XML,否则我们不知道失败的原因.

有办法解决这个问题吗?

例如

var restClient = new RestClient(baseURL);
var request = new RestRequest(uri);
request.Method = Method.POST;
var response = restClient.Execute<User>(request);
Run Code Online (Sandbox Code Playgroud)

在执行上述方法时,API可以返回Error xml对象.如何在失败时获取Error对象,在成功时获得User?

AJ *_*son 5

这是可能的,虽然代码有点难看.RestSharp允许您指定自己的XML反序列化器,因此我们需要这样做才能使其工作.

首先,你需要一个可以存储a Error或a 的数据类型User(我使它成为通用的,因此它不仅适用于用户):

public class Result<T>
{
    public T Data { get; set; }
    public Error Error { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

所以我的想法是,现在当你执行请求时,你要求RestSharp Result<User>而不仅仅是a User,即:

var result = client.Execute<Result<User>>(request);
Run Code Online (Sandbox Code Playgroud)

现在,这是将反序列化为a Error或a 所需的魔力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;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你会像这样连线:

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...
}
Run Code Online (Sandbox Code Playgroud)