Creating a reusable method timeout class in C# - c#

I am trying to create a class that lets me call methods with a specified timout. I have the actual timeout implementation working, but am having trouble encapsulating this into a class successfully.
I have decided at this time to limit myself to working with just the 5 Action delegates to put a timeout on methods that take 0 - 4 arguments. For the purposes of this question i will use the one argument variant of Action.
My Ideal calling syntax would be something like this:
Action<int> a = new TimeoutAction(i => i + 1)
{
Timeout = Timespan.FromSeconds(10)
}
or this:
Action<int> a = (x => x + 1).Timeout(Timespan.FromSeconds(10))
I am almost sure that the first version isnt possible as there is no way to inherit from a delegate. The second may be possible by using an extension method on the Delegate type.
A final fallback would be to create static methods that take in the appropriate delegate type and return a Delegate with the same signature but with the timeouts included.
Any suggestions or ideas?

Your last suggestion would be the right way:
A final fallback would be to create
static methods that take in the
appropriate delegate type and return a
Delegate with the same signature but
with the timeouts included.
In other words:
public static Action<T> Timeout<T>(this Action<T> action, TimeSpan timeSpan);
public static Action<T1, T2> Timeout<T1, T2>(this Action<T1, T2> action, TimeSpan timeSpan);
public static Func<T, TResult> Timeout<T, TResult>(this Func<T, TResult> action, TimeSpan timeSpan);
public static Func<T1, T2, TResult> Timeout<T1, T2, TResult>(this Func<T1, T2, TResult> action, TimeSpan timeSpan);
/* snip the rest of the Action<...> and Func<...> overloads */
"Why can't I just declare one method?"
You could declare one method that accepts a Delegate and returns a Delegate, but then you'd lose the delegate type information (your second example wouldn't compile).
Unfortunately, the following example isn't valid C# -- you can't use Delegate as a type parameter constraint:
public static TDelegate Timeout<TDelegate>(this TDelegate d, Timespan timespan) where TDelegate : Delegate;

Use AOP for that. Either PostSharp or DynamicProxy

How about something like the approach to a Timed Lock as described here?

Well, a lambda expression won't "have a type" (anything you can 'dot' or extension method) until you wrap it in e.g.
new DelType(lambda)
or
Stat.Method(lambda)
or otherwise provide context, so I suggest the final option (static method):
Timeout.Action(lambda, timeoutVal)

Related

Generic method with Func parameter, Func contravariance doesn't seem to work

.NET's Func<T1, T2, TResult> is written so that T1 and T2 are contravariant and TResult is covariant.
This means that:
Func<object, object, bool> objectEquals = object.Equals;
Func<MyObject, MyObject, bool> myObjectEquals = objectEquals;
is a valid assignment.
Now, I have a class with methods along these lines:
public void DoSomething<T>(T value)
{
DoSomethingCore(T, Object.Equals);
}
protected abstract void DoSomethingCore<T>(T value, Func<T, T, bool> equals);
The code would not compile, with the following error:
CS0123 No overload for 'object.Equals(object, object)' matches delegate 'Func<T, T, bool>'
Why does contravariance not seem to work in this case?
Contravariance, and variance in general, don't work with value types.
Hence, you must constrain the DoSomething method to only work with reference types if you want to use Object.Equals as the function for Func<T, T, bool>.
In other words, add where T : class in the method signature:
public void DoSomething<T>(T value) where T : class
{
DoSomethingCore(T, Object.Equals);
}

How do I cast a method group to an object? "Cannot convert method group 'XXX' to non-delegate type 'object'."

Occasionally I run into the problem of needing to execute a generic method without knowing its type.
I know I can do this each time using reflection, however I am trying to write a helper method:
public static object InvokeGeneric<T>(this T #this,
Expression<Func<T, object>> method,
Type genericType,
params object[] arguments)
{
// I think I know what to do here
// look at the expression tree, grab
// the method info, do the
// reflection in here, etc.
return null;
}
So that I can do this:
this._myService.InvokeGeneric(
e => e.MyGenericMethod, // interface IMyService { void MyGenericMethod<T>(T t); }
typeof(MyGenericType),
myArg);
However I am getting this error: Cannot convert method group 'XXX' to non-delegate type 'object'.
Without changing my calling syntax, how can I change my method signature of my helper method to do what I want?
EDIT:
I got it down to:
this._myService.InvokeGeneric<IMyService, object, MyArgType>(e => e.MyGenericMethod, typeof(MyGenericType), myArg);
The downside (besides extra typing) is that you'd need an overload for each generic variation of Func<> and Action<> that you'd want to support.
public static object InvokeGeneric<T, T1>(this object #this, Expression<Func<T, Action<T1>>> method, Type genericType, params object[] arguments)
{ }
public static object InvokeGeneric<T, T1, T2>(this object #this, Expression<Func<T, Action<T1, T2>>> method, Type genericType, params object[] arguments)
{ }
etc. I'm going to use that solution, but if anyone has something that meets the briefer syntax let me know and I'll accept it. Reading a bit about method groups made me realize my syntax is ambiguous, potentially, if there are overloads, meaning a strongly-typed one like this is probably better, anyway.

Lambda expression arguments

I'm trying to create an extension method for Moq where I can send in an expression to be used in an async return function. However this question is not really Moq specific. Here's what I have so far:
public static IReturnsResult<TMock> ReturnsAsync<TMock, TResult, T>(this IReturns<TMock, Task<TResult>> setup, Func<T, TResult> valueFunc) where TMock : class
{
return setup.Returns(Task.FromResult(valueFunc.Invoke(default(T))));
}
This is how I'm hoping to use it.
repo.Setup(x => x.FindAsync(It.IsAny<Expression<Func<T, bool>>>())).ReturnsAsync((Expression<Func<T, bool>> e) => context.GetSet<T>().FirstOrDefault(e));
Now I don't really know how all of this works and the thing I can't figure out is how to I get the expression passed on into the ReturnsAsync function so I can use it as the argument instead of the default(T) that I put there as a placeholder.
As expected the "e" variable here becomes null.
This method will do what you want:
public static IReturnsResult<TMock> ReturnsAsync<TMock, TResult, T>(
this IReturns<TMock, Task<TResult>> setup,
Func<Expression<Func<TResult, T>>, TResult> valueFunc)
where TMock : class
{
return setup.Returns<Expression<Func<TResult, T>>>(
e => Task.FromResult(valueFunc(e)));
}
Then use it like so:
repo.Setup(x => x.FindAsync(It.IsAny<Expression<Func<T, bool>>>()))
.ReturnsAsync<IRepository, int, bool>(e => context.GetSet<T>().FirstOrDefault(e));
Essentially, this version of ReturnsAsync takes a function that expects a predicate function (which is e) and returns a T. This allows you to then execute the predicate against your test data set (context.GetSet<T>.FirstOrDefault). Also, I used the overload of Returns that accepts a type parameter; this is used to forward the arguments from the Setup call to the function specified as the Returns argument.
Your version's signature only specified the predicate, so you had no way to execute it against your test data. You also had the T and TResult type parameters backwards in the valueFunc parameter's type.

Get MethodInfo from expression without knowing method signature

I'm trying to pass an expression that describes a method but I want the argument to be strongly typed and I don't want to have to know the method signature or pass the arguments in the expression, something like this:
GetMethod<MyClass>(c => c.DoSomething);
Where DoSomething could have a method signature like this... string DoSomething(int id, int count)
I know I can do something like this:
MemberInfo GetMethod<T>(Expression<Func<T, Delegate>> expression);
//implementation
GetMethod<MyClass>(c => new Func<int, int, string>(c.DoSomething))
But frankly, this is quite ugly.
Is this possible?
Just have an overload for each possible Action/Func. It won't cover all possibilities (have an extra overload that you've shown there to cover all edge cases) but it'll handle most of them.
The body of each of the action/func overloads can just call the overload that you've shown above for the actual implementation.
public MemberInfo GetMethod<T1, T2>(Expression<Func<T1, Func<T2>>> expression)
{
return GetMethodImpl(expression);
}
public MemberInfo GetMethod<T1, T2, T3>(Expression<Func<T1, Func<T2, T3>>> expression)
{
return GetMethodImpl(expression);
}
public MemberInfo GetMethod<T1, T2>(Expression<Func<T1, Action<T2>>> expression)
{
return GetMethodImpl(expression);
}
//...
GetMethodImpl can then be implemented like so:
private MemberInfo GetMethodImpl<T1, T2>(Expression<Func<T1, T2>> expression)
{
}
That will be able to be just a slight modification of your existing GetMethod implementation. T2 will be your delegate; you may need to cast it to Delegate, depending on how you use it.

Func<T, TResult> for with void TResult?

Func<> is very convenient in .NET. Is there a way i can specify the param type and have the result value as void? I'd like to pass void Write(string) as a parameter.
Action<T> - "Encapsulates a method that takes a single parameter and does not return a value"
I believe you're looking for the Action<T> family of delegate types.
It's not perfect, but sometimes when I want to fake this behavior against an existing function (and I'd rather not re-implement it as Action<TResult>) I'll just return null and throw the value away.
Func<T, TResult> myFunc = (inVar) =>
{
// do work...
return null as object;
};

Categories