tags:

views:

609

answers:

4

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?

A: 

Use AOP for that. Either PostSharp or DynamicProxy

Krzysztof Koźmic
A: 

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)
Brian
A: 

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

Erich Mirabal
+2  A: 

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;
Tim Robinson