所以我一直在修補Linq.Expressions(如果有人可以建議一個更合適或更優雅的方式來做我所做的事情,請隨時參加),並試圖做一些事情已經碰壁了。Linq.Expression TryCatch - 將異常傳遞給Catch Block?
讓我們想象一下,我們有一個簡單的數學類:
public class SimpleMath {
public int AddNumbers(int number1, int number2) {
return number1 + number2;
}
}
我決定我想我們AddNumbers
方法轉換成一個簡單的Func<object, object, object>
委託。
要做到這一點,我做了以下內容:
// Two collections, one for Type Object paramaters and one for converting to Type int.
List<ParameterExpression> parameters = new List<ParameterExpression>();
List<Expression> convertedParameters = new List<Expression>();
// Populate collections with Parameter and conversion
ParameterExpression parameter1 = Expression.Parameter(typeof(object));
parameters.Add(parameter1);
convertedParameters.Add(Expression.Convert(parameter1, typeof(int)));
ParameterExpression parameter2 = Expression.Parameter(typeof(object));
parameters.Add(parameter2);
convertedParameters.Add(Expression.Convert(parameter2, typeof(int)));
// Create instance of SimpleMath
SimpleMath simpleMath = new SimpleMath();
// Get the MethodInfo for the AddNumbers method
MethodInfo addNumebrsMethodInfo = simpleMath.GetType().GetMethods().Where(x => x.Name == "AddNumbers").ToArray()[0];
// Create MethodCallExpression using the SimpleMath object, the MethodInfo of the method we want and the converted parameters
MethodCallExpression returnMethodWithParameters = Expression.Call(Expression.Constant(simpleMath), addNumebrsMethodInfo, convertedParameters);
// Convert the MethodCallExpression to return an Object rather than int
UnaryExpression returnMethodWithParametersAsObject = Expression.Convert(returnMethodWithParameters, typeof(object));
// Create the Func<object, object, object> with our converted Expression and Parameters of Type Object
Func<object, object, object> func = Expression.Lambda<Func<object, object, object>>(returnMethodWithParametersAsObject, parameters).Compile();
object result = func(20, 40); // result = 60
所以,如果你運行該代碼func
應該返回簡單的計算。然而,它接受類型對象,這顯然離開它打開在運行時的問題,例如參數:
object result1 = func(20, "f"); // Throws InvalidCastException
所以我想換的方法,在Try...Catch
(顯然這個確切的問題將在編譯有所回升如果我們正在處理直接調用AddNumbers
並傳遞一個字符串作爲參數)。
以抓住這個例外,我可以做到以下幾點:
TryExpression tryCatchMethod = TryExpression.TryCatch(returnMethodWithParametersAsObject, Expression.Catch(typeof(InvalidCastException), Expression.Constant(55, typeof(object))));
Func<object, object, object> func = Expression.Lambda<Func<object, object, object>>(tryCatchMethod, parameters).Compile();
object result = func(20, "f"); // result = 55
的TryExpression.TryCatch
需要一個表達的身體,然後CatchBlock處理程序的集合。 returnMethodWithParametersAsObject
是我們希望包裹的表達,Expression.Catch
定義了我們想捕獲異常是InvalidCastException類型和它表達的身體是一個常數,55
所以異常的處理,但除非我想這是沒有多大用處在拋出異常時總是返回一個靜態值。於是久違的SimpleMath
I類添加一個新方法HandleException
:
public class SimpleMath {
public int AddNumbers(int number1, int number2) {
return number1 + number2;
}
public int HandleException() {
return 100;
}
}
而且同樣的過程上面我轉換的新方法的表達式:
MethodInfo handleExceptionMethodInfo = simpleMath.GetType().GetMethods().Where(x => x.Name == "HandleException").ToArray()[0];
MethodCallExpression returnMethodWithParameters2 = Expression.Call(Expression.Constant(simpleMath), handleExceptionMethodInfo);
UnaryExpression returnMethodWithParametersAsObject2 = Expression.Convert(returnMethodWithParameters2, typeof(object));
然後創建TryCatch塊時使用它:
TryExpression tryCatchMethod2 = TryExpression.TryCatch(returnMethodWithParametersAsObject, Expression.Catch(typeof(InvalidCastException), returnMethodWithParametersAsObject2));
Func<object, object, object> func = Expression.Lambda<Func<object, object, object>>(tryCatchMethod2, parameters).Compile();
object result = func(20, "f"); // result = 100
所以當InvalidCastException
拋出的SimpleMath.HandleException
方法這段時間將被執行。到目前爲止,如果出現異常,我現在可以執行一些代碼。
我現在的問題是,在一個正常的行內嘗試...趕上塊你實際上有你的處置異常對象。例如。
try {
// Do stuff that causes an exception
} catch (InvalidCastException ex) {
// Do stuff with InvalidCastException ex
}
時拋出一個異常,我可以執行代碼,但我似乎無法弄清楚如何真正得到我的手異常對象上,就像您在普通try ... catch塊。
任何幫助,將不勝感激!
p.s.我知道你不會以上述方式組織任何事情,但我認爲有必要舉例說明我想要做什麼的機制。
問題比較對我的知識,而是一個建議,可以幫助有關傳遞異常太複雜:抓{拋出;}。這會將你的異常傳遞給調用方法(你必須處理它或程序將停止!)。如果你想把你的手放在一個已經存在的函數的例外,把它作爲一個動作/ func在你自己的TryCatch方法中,如果發生了什麼錯誤,返回一個異常,如果一切正常,你認爲是好的(空?) – Kinxil