在Web服务中出现异常和ASP.NET Web API返回异常的JSON响应,如下列:
HTTP/1.1 500 Internal Server Error
Content-Type: application/json; charset=utf-8
{ "Message":"An error has occurred.",
"ExceptionMessage":"Incorrect syntax near 'FooBar'.",
"ExceptionType":"System.Data.SqlClient.SqlException",
"StackTrace":"at System.Web.Http.ApiController.blah.blah.blah" }
我想重新在客户端的例外。 我想对一个SQLException对象的响应转换(在下面的例子中),然后抛出异常。 一些博客已经使用Activator.CreateInstance()和Type.GetType()用于在运行时,在字符串类型名称的对象提到有的已提到使用的动态。 然而,我无法弄清楚如何正确地使用它。 我将不胜感激,如果有人可以教我。 谢谢!
public class ExceptionResponse
{
public string Message { get; set; }
public string ExceptionType { get; set; }
public string ExceptionMessage { get; set; }
public string StackTrace { get; set; }
}
ExceptionResponse response = httpContent.ReadAsAsync<ExceptionResponse>().Result;
Type exceptionType = Type.GetType(response.ExceptionType);
throw Activator.CreateInstance(exceptionType, new object[]);
// Visual Studio indicates error: The type caught or throw must be derived from System.Exception
据我所知,您尝试处理它通过HTTP reciving作为一个JSON格式的消息异常。 所以,你可以尝试序列化(解析)HTTP响应,并创建ExceptionResponse的新实例。 例如:
using System.Web.Script.Serialization;
您的异常类将是这样的:
public class ExceptionResponse : Exception {
public string ExceptionType { get; set; }
public string ExceptionMessage { get; set; }
}
调用:
var httpResponse = @"{ ""Message"":""An error has occurred."", ""ExceptionMessage"":""Incorrect syntax near 'FooBar'."", ""ExceptionType"":""System.Data.SqlClient.SqlException"", ""StackTrace"":""at System.Web.Http.ApiController.blah.blah.blah"" }";
var e = new JavaScriptSerializer().Deserialize<ExceptionResponse>(httpResponse);
throw e;
最后,我发现从一个例子Github上展示了如何使用反射来重新创建一个SQL例外。
public static class SqlExceptionCreator
{
public static SqlException Create(string message, int errorCode)
{
SqlException exception = Instantiate<SqlException>();
SetProperty(exception, "_message", message);
var errors = new ArrayList();
var errorCollection = Instantiate<SqlErrorCollection>();
SetProperty(errorCollection, "errors", errors);
var error = Instantiate<SqlError>();
SetProperty(error, "number", errorCode);
errors.Add(error);
SetProperty(exception, "_errors", errorCollection);
return exception;
}
private static T Instantiate<T>() where T : class
{
return System.Runtime.Serialization.FormatterServices.GetUninitializedObject(typeof(T)) as T;
}
private static void SetProperty<T>(T targetObject, string fieldName, object value)
{
var field = typeof(T).GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance);
if (field != null)
{
field.SetValue(targetObject, value);
}
else
{
throw new InvalidOperationException("No field with name " + fieldName);
}
}
}