Skip to content

Commit a9a4d93

Browse files
committed
Added helper methods as suggested in #268.
1 parent cec830b commit a9a4d93

File tree

2 files changed

+377
-2
lines changed

2 files changed

+377
-2
lines changed

src/DotNext.Tests/DelegateHelpersTests.cs

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ public static void ContravarianceTest()
2121
[Fact]
2222
public static void ChangeDelegateType()
2323
{
24-
WaitCallback callback = static obj => { };
25-
callback += static obj => { };
24+
WaitCallback callback = static _ => { };
25+
callback += static _ => { };
2626
var result = callback.ChangeType<SendOrPostCallback>();
2727
NotNull(result);
2828
var list1 = callback.GetInvocationList().Select(static d => d.Method);
@@ -603,4 +603,39 @@ public static void HideReturnValue2()
603603

604604
int ChangeValue(int value) => box.Value = value;
605605
}
606+
607+
[Fact]
608+
public static void TryInvokeAction()
609+
{
610+
static MethodInfo GetMethod(int argCount)
611+
{
612+
const BindingFlags flags = BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly;
613+
return Single(typeof(DelegateHelpers).GetMethods(flags),
614+
candidate => candidate.Name == nameof(DelegateHelpers.TryInvoke) && candidate.GetParameters().Length == argCount + 1);
615+
}
616+
617+
var successValue = Expression.Empty();
618+
var failedValue = Expression.Throw(Expression.New(typeof(ArithmeticException)), typeof(void));
619+
for (var argCount = 0; argCount <= 10; argCount++)
620+
{
621+
var types = new Type[argCount];
622+
Array.Fill(types, typeof(string));
623+
var actionType = Expression.GetActionType(types);
624+
var parameters = new ParameterExpression[argCount];
625+
parameters.AsSpan().ForEach(static (ref ParameterExpression p, int _) => p = Expression.Parameter(typeof(string)));
626+
//prepare args
627+
var args = new object[parameters.LongLength + 1];
628+
Array.Fill(args, string.Empty);
629+
//find method to test
630+
var method = types is [] ? GetMethod(argCount) : GetMethod(argCount).MakeGenericMethod(types);
631+
//check success scenario
632+
args[0] = Expression.Lambda(actionType, successValue, parameters).Compile();
633+
var result = (Exception)method.Invoke(null, args);
634+
Null(result);
635+
//check failure
636+
args[0] = Expression.Lambda(actionType, failedValue, parameters).Compile();
637+
result = (Exception)method.Invoke(null, args);
638+
IsType<ArithmeticException>(result);
639+
}
640+
}
606641
}
Lines changed: 340 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,340 @@
1+
namespace DotNext;
2+
3+
public partial class DelegateHelpers
4+
{
5+
/// <summary>
6+
/// Invokes the action without throwing the exception.
7+
/// </summary>
8+
/// <param name="action">The action to be invoked.</param>
9+
/// <returns>The exception caused by <paramref name="action"/>; or <see langword="null"/>, if the delegate is called successfully.</returns>
10+
public static Exception? TryInvoke(this Action action)
11+
{
12+
var result = default(Exception);
13+
try
14+
{
15+
action();
16+
}
17+
catch (Exception e)
18+
{
19+
result = e;
20+
}
21+
22+
return result;
23+
}
24+
25+
/// <summary>
26+
/// Invokes the action without throwing the exception.
27+
/// </summary>
28+
/// <typeparam name="T">The type of the first action argument.</typeparam>
29+
/// <param name="action">The action to be invoked.</param>
30+
/// <param name="arg">The first action argument.</param>
31+
/// <returns>The exception caused by <paramref name="action"/>; or <see langword="null"/>, if the delegate is called successfully.</returns>
32+
public static Exception? TryInvoke<T>(this Action<T> action, T arg)
33+
{
34+
var result = default(Exception);
35+
try
36+
{
37+
action(arg);
38+
}
39+
catch (Exception e)
40+
{
41+
result = e;
42+
}
43+
44+
return result;
45+
}
46+
47+
/// <summary>
48+
/// Invokes the action without throwing the exception.
49+
/// </summary>
50+
/// <typeparam name="T1">The type of the first action argument.</typeparam>
51+
/// <typeparam name="T2">The type of the second action argument.</typeparam>
52+
/// <param name="action">The action to be invoked.</param>
53+
/// <param name="arg1">The first action argument.</param>
54+
/// <param name="arg2">The second action argument.</param>
55+
/// <returns>The exception caused by <paramref name="action"/>; or <see langword="null"/>, if the delegate is called successfully.</returns>
56+
public static Exception? TryInvoke<T1, T2>(this Action<T1, T2> action, T1 arg1, T2 arg2)
57+
{
58+
var result = default(Exception);
59+
try
60+
{
61+
action(arg1, arg2);
62+
}
63+
catch (Exception e)
64+
{
65+
result = e;
66+
}
67+
68+
return result;
69+
}
70+
71+
/// <summary>
72+
/// Invokes the action without throwing the exception.
73+
/// </summary>
74+
/// <typeparam name="T1">The type of the first action argument.</typeparam>
75+
/// <typeparam name="T2">The type of the second action argument.</typeparam>
76+
/// <typeparam name="T3">The type of the third action argument.</typeparam>
77+
/// <param name="action">The action to be invoked.</param>
78+
/// <param name="arg1">The first action argument.</param>
79+
/// <param name="arg2">The second action argument.</param>
80+
/// <param name="arg3">The third action argument.</param>
81+
/// <returns>The exception caused by <paramref name="action"/>; or <see langword="null"/>, if the delegate is called successfully.</returns>
82+
public static Exception? TryInvoke<T1, T2, T3>(this Action<T1, T2, T3> action, T1 arg1, T2 arg2, T3 arg3)
83+
{
84+
var result = default(Exception);
85+
try
86+
{
87+
action(arg1, arg2, arg3);
88+
}
89+
catch (Exception e)
90+
{
91+
result = e;
92+
}
93+
94+
return result;
95+
}
96+
97+
/// <summary>
98+
/// Invokes the action without throwing the exception.
99+
/// </summary>
100+
/// <typeparam name="T1">The type of the first action argument.</typeparam>
101+
/// <typeparam name="T2">The type of the second action argument.</typeparam>
102+
/// <typeparam name="T3">The type of the third action argument.</typeparam>
103+
/// <typeparam name="T4">The type of the fourth action argument.</typeparam>
104+
/// <param name="action">The action to be invoked.</param>
105+
/// <param name="arg1">The first action argument.</param>
106+
/// <param name="arg2">The second action argument.</param>
107+
/// <param name="arg3">The third action argument.</param>
108+
/// <param name="arg4">The fourth action argument.</param>
109+
/// <returns>The exception caused by <paramref name="action"/>; or <see langword="null"/>, if the delegate is called successfully.</returns>
110+
public static Exception? TryInvoke<T1, T2, T3, T4>(this Action<T1, T2, T3, T4> action, T1 arg1, T2 arg2, T3 arg3, T4 arg4)
111+
{
112+
var result = default(Exception);
113+
try
114+
{
115+
action(arg1, arg2, arg3, arg4);
116+
}
117+
catch (Exception e)
118+
{
119+
result = e;
120+
}
121+
122+
return result;
123+
}
124+
125+
/// <summary>
126+
/// Invokes the action without throwing the exception.
127+
/// </summary>
128+
/// <typeparam name="T1">The type of the first action argument.</typeparam>
129+
/// <typeparam name="T2">The type of the second action argument.</typeparam>
130+
/// <typeparam name="T3">The type of the third action argument.</typeparam>
131+
/// <typeparam name="T4">The type of the fourth action argument.</typeparam>
132+
/// <typeparam name="T5">The type of the fifth action argument.</typeparam>
133+
/// <param name="action">The action to be invoked.</param>
134+
/// <param name="arg1">The first action argument.</param>
135+
/// <param name="arg2">The second action argument.</param>
136+
/// <param name="arg3">The third action argument.</param>
137+
/// <param name="arg4">The fourth action argument.</param>
138+
/// <param name="arg5">The fifth action argument.</param>
139+
/// <returns>The exception caused by <paramref name="action"/>; or <see langword="null"/>, if the delegate is called successfully.</returns>
140+
public static Exception? TryInvoke<T1, T2, T3, T4, T5>(this Action<T1, T2, T3, T4, T5> action, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5)
141+
{
142+
var result = default(Exception);
143+
try
144+
{
145+
action(arg1, arg2, arg3, arg4, arg5);
146+
}
147+
catch (Exception e)
148+
{
149+
result = e;
150+
}
151+
152+
return result;
153+
}
154+
155+
/// <summary>
156+
/// Invokes the action without throwing the exception.
157+
/// </summary>
158+
/// <typeparam name="T1">The type of the first action argument.</typeparam>
159+
/// <typeparam name="T2">The type of the second action argument.</typeparam>
160+
/// <typeparam name="T3">The type of the third action argument.</typeparam>
161+
/// <typeparam name="T4">The type of the fourth action argument.</typeparam>
162+
/// <typeparam name="T5">The type of the fifth action argument.</typeparam>
163+
/// <typeparam name="T6">The type of the sixth action argument.</typeparam>
164+
/// <param name="action">The action to be invoked.</param>
165+
/// <param name="arg1">The first action argument.</param>
166+
/// <param name="arg2">The second action argument.</param>
167+
/// <param name="arg3">The third action argument.</param>
168+
/// <param name="arg4">The fourth action argument.</param>
169+
/// <param name="arg5">The fifth action argument.</param>
170+
/// <param name="arg6">The sixth action argument.</param>
171+
/// <returns>The exception caused by <paramref name="action"/>; or <see langword="null"/>, if the delegate is called successfully.</returns>
172+
public static Exception? TryInvoke<T1, T2, T3, T4, T5, T6>(this Action<T1, T2, T3, T4, T5, T6> action, T1 arg1, T2 arg2, T3 arg3, T4 arg4,
173+
T5 arg5, T6 arg6)
174+
{
175+
var result = default(Exception);
176+
try
177+
{
178+
action(arg1, arg2, arg3, arg4, arg5, arg6);
179+
}
180+
catch (Exception e)
181+
{
182+
result = e;
183+
}
184+
185+
return result;
186+
}
187+
188+
/// <summary>
189+
/// Invokes the action without throwing the exception.
190+
/// </summary>
191+
/// <typeparam name="T1">The type of the first action argument.</typeparam>
192+
/// <typeparam name="T2">The type of the second action argument.</typeparam>
193+
/// <typeparam name="T3">The type of the third action argument.</typeparam>
194+
/// <typeparam name="T4">The type of the fourth action argument.</typeparam>
195+
/// <typeparam name="T5">The type of the fifth action argument.</typeparam>
196+
/// <typeparam name="T6">The type of the sixth action argument.</typeparam>
197+
/// <typeparam name="T7">The type of the seventh action argument.</typeparam>
198+
/// <param name="action">The action to be invoked.</param>
199+
/// <param name="arg1">The first action argument.</param>
200+
/// <param name="arg2">The second action argument.</param>
201+
/// <param name="arg3">The third action argument.</param>
202+
/// <param name="arg4">The fourth action argument.</param>
203+
/// <param name="arg5">The fifth action argument.</param>
204+
/// <param name="arg6">The sixth action argument.</param>
205+
/// <param name="arg7">The seventh action argument.</param>
206+
/// <returns>The exception caused by <paramref name="action"/>; or <see langword="null"/>, if the delegate is called successfully.</returns>
207+
public static Exception? TryInvoke<T1, T2, T3, T4, T5, T6, T7>(this Action<T1, T2, T3, T4, T5, T6, T7> action, T1 arg1, T2 arg2, T3 arg3, T4 arg4,
208+
T5 arg5, T6 arg6, T7 arg7)
209+
{
210+
var result = default(Exception);
211+
try
212+
{
213+
action(arg1, arg2, arg3, arg4, arg5, arg6, arg7);
214+
}
215+
catch (Exception e)
216+
{
217+
result = e;
218+
}
219+
220+
return result;
221+
}
222+
223+
/// <summary>
224+
/// Invokes the action without throwing the exception.
225+
/// </summary>
226+
/// <typeparam name="T1">The type of the first action argument.</typeparam>
227+
/// <typeparam name="T2">The type of the second action argument.</typeparam>
228+
/// <typeparam name="T3">The type of the third action argument.</typeparam>
229+
/// <typeparam name="T4">The type of the fourth action argument.</typeparam>
230+
/// <typeparam name="T5">The type of the fifth action argument.</typeparam>
231+
/// <typeparam name="T6">The type of the sixth action argument.</typeparam>
232+
/// <typeparam name="T7">The type of the seventh action argument.</typeparam>
233+
/// <typeparam name="T8">The type of the eighth action argument.</typeparam>
234+
/// <param name="action">The action to be invoked.</param>
235+
/// <param name="arg1">The first action argument.</param>
236+
/// <param name="arg2">The second action argument.</param>
237+
/// <param name="arg3">The third action argument.</param>
238+
/// <param name="arg4">The fourth action argument.</param>
239+
/// <param name="arg5">The fifth action argument.</param>
240+
/// <param name="arg6">The sixth action argument.</param>
241+
/// <param name="arg7">The seventh action argument.</param>
242+
/// <param name="arg8">The seventh action argument.</param>
243+
/// <returns>The exception caused by <paramref name="action"/>; or <see langword="null"/>, if the delegate is called successfully.</returns>
244+
public static Exception? TryInvoke<T1, T2, T3, T4, T5, T6, T7, T8>(this Action<T1, T2, T3, T4, T5, T6, T7, T8> action, T1 arg1, T2 arg2, T3 arg3, T4 arg4,
245+
T5 arg5, T6 arg6, T7 arg7, T8 arg8)
246+
{
247+
var result = default(Exception);
248+
try
249+
{
250+
action(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
251+
}
252+
catch (Exception e)
253+
{
254+
result = e;
255+
}
256+
257+
return result;
258+
}
259+
260+
/// <summary>
261+
/// Invokes the action without throwing the exception.
262+
/// </summary>
263+
/// <typeparam name="T1">The type of the first action argument.</typeparam>
264+
/// <typeparam name="T2">The type of the second action argument.</typeparam>
265+
/// <typeparam name="T3">The type of the third action argument.</typeparam>
266+
/// <typeparam name="T4">The type of the fourth action argument.</typeparam>
267+
/// <typeparam name="T5">The type of the fifth action argument.</typeparam>
268+
/// <typeparam name="T6">The type of the sixth action argument.</typeparam>
269+
/// <typeparam name="T7">The type of the seventh action argument.</typeparam>
270+
/// <typeparam name="T8">The type of the eighth action argument.</typeparam>
271+
/// <typeparam name="T9">The type of the ninth action argument.</typeparam>
272+
/// <param name="action">The action to be invoked.</param>
273+
/// <param name="arg1">The first action argument.</param>
274+
/// <param name="arg2">The second action argument.</param>
275+
/// <param name="arg3">The third action argument.</param>
276+
/// <param name="arg4">The fourth action argument.</param>
277+
/// <param name="arg5">The fifth action argument.</param>
278+
/// <param name="arg6">The sixth action argument.</param>
279+
/// <param name="arg7">The seventh action argument.</param>
280+
/// <param name="arg8">The seventh action argument.</param>
281+
/// <param name="arg9">The ninth action argument.</param>
282+
/// <returns>The exception caused by <paramref name="action"/>; or <see langword="null"/>, if the delegate is called successfully.</returns>
283+
public static Exception? TryInvoke<T1, T2, T3, T4, T5, T6, T7, T8, T9>(this Action<T1, T2, T3, T4, T5, T6, T7, T8, T9> action, T1 arg1, T2 arg2, T3 arg3, T4 arg4,
284+
T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9)
285+
{
286+
var result = default(Exception);
287+
try
288+
{
289+
action(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
290+
}
291+
catch (Exception e)
292+
{
293+
result = e;
294+
}
295+
296+
return result;
297+
}
298+
299+
/// <summary>
300+
/// Invokes the action without throwing the exception.
301+
/// </summary>
302+
/// <typeparam name="T1">The type of the first action argument.</typeparam>
303+
/// <typeparam name="T2">The type of the second action argument.</typeparam>
304+
/// <typeparam name="T3">The type of the third action argument.</typeparam>
305+
/// <typeparam name="T4">The type of the fourth action argument.</typeparam>
306+
/// <typeparam name="T5">The type of the fifth action argument.</typeparam>
307+
/// <typeparam name="T6">The type of the sixth action argument.</typeparam>
308+
/// <typeparam name="T7">The type of the seventh action argument.</typeparam>
309+
/// <typeparam name="T8">The type of the eighth action argument.</typeparam>
310+
/// <typeparam name="T9">The type of the ninth action argument.</typeparam>
311+
/// <typeparam name="T10">The type of the tenth action argument.</typeparam>
312+
/// <param name="action">The action to be invoked.</param>
313+
/// <param name="arg1">The first action argument.</param>
314+
/// <param name="arg2">The second action argument.</param>
315+
/// <param name="arg3">The third action argument.</param>
316+
/// <param name="arg4">The fourth action argument.</param>
317+
/// <param name="arg5">The fifth action argument.</param>
318+
/// <param name="arg6">The sixth action argument.</param>
319+
/// <param name="arg7">The seventh action argument.</param>
320+
/// <param name="arg8">The seventh action argument.</param>
321+
/// <param name="arg9">The ninth action argument.</param>
322+
/// <param name="arg10">The tenth action argument.</param>
323+
/// <returns>The exception caused by <paramref name="action"/>; or <see langword="null"/>, if the delegate is called successfully.</returns>
324+
public static Exception? TryInvoke<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(this Action<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> action, T1 arg1,
325+
T2 arg2, T3 arg3, T4 arg4,
326+
T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10)
327+
{
328+
var result = default(Exception);
329+
try
330+
{
331+
action(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10);
332+
}
333+
catch (Exception e)
334+
{
335+
result = e;
336+
}
337+
338+
return result;
339+
}
340+
}

0 commit comments

Comments
 (0)