Created
July 26, 2012 23:11
-
-
Save phatboyg/3185165 to your computer and use it in GitHub Desktop.
Method Async Proxy
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
public interface IProxyAsyncResult<T> : | |
IAsyncResult | |
{ | |
T Result { get; } | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Linq.Expressions; | |
public static class Proxy<T> | |
where T : class | |
{ | |
public static Proxy<T,TResult> Create<TResult>(Expression<Func<T, TResult>> targetExpression) | |
{ | |
var methodCallExpression = targetExpression.Body as MethodCallExpression; | |
if (methodCallExpression == null) | |
throw new ArgumentException("The target must be a member expression", "targetExpression"); | |
var method = methodCallExpression.Method; | |
if (method == null) | |
throw new ArgumentException("The target could not be cast to a member", "targetExpression"); | |
var call = targetExpression.Compile(); | |
return new Proxy<T, TResult>(call); | |
} | |
} | |
public class Proxy<T, TResult> | |
where T : class | |
{ | |
readonly Func<T, TResult> _call; | |
public Proxy(Func<T, TResult> call) | |
{ | |
_call = call; | |
} | |
public IAsyncResult BeginCall(T target, AsyncCallback callback, object state) | |
{ | |
var asyncProxy = new ProxyAsyncResult<T, TResult>(target, _call, callback, state); | |
return asyncProxy; | |
} | |
public TResult EndCall(IAsyncResult asyncResult) | |
{ | |
var asyncProxy = asyncResult as IProxyAsyncResult<TResult>; | |
if(asyncProxy == null) | |
throw new ArgumentException("The result was not an async proxy", "asyncResult"); | |
return asyncProxy.Result; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Threading; | |
public class ProxyAsyncResult<T, TResult> : | |
IProxyAsyncResult<TResult> | |
where T : class | |
{ | |
readonly Func<T, TResult> _call; | |
readonly AsyncCallback _callback; | |
readonly object _state; | |
readonly T _target; | |
volatile bool _complete; | |
ManualResetEvent _event; | |
Exception _exception; | |
TResult _result; | |
public ProxyAsyncResult(T target, Func<T, TResult> call, AsyncCallback callback, object state) | |
{ | |
_target = target; | |
_call = call; | |
_callback = callback; | |
_state = state; | |
ThreadPool.QueueUserWorkItem(Run, this); | |
} | |
public bool IsCompleted | |
{ | |
get { return _complete; } | |
} | |
public WaitHandle AsyncWaitHandle | |
{ | |
get | |
{ | |
lock (this) | |
{ | |
if (_event == null) | |
_event = new ManualResetEvent(_complete); | |
} | |
return _event; | |
} | |
} | |
public object AsyncState | |
{ | |
get { return _state; } | |
} | |
public bool CompletedSynchronously | |
{ | |
get { return false; } | |
} | |
TResult IProxyAsyncResult<TResult>.Result | |
{ | |
get | |
{ | |
if (_exception != null) | |
throw _exception; | |
return _result; | |
} | |
} | |
void Run(object state) | |
{ | |
try | |
{ | |
_result = _call(_target); | |
} | |
catch (Exception ex) | |
{ | |
_exception = ex; | |
} | |
finally | |
{ | |
Complete(); | |
} | |
} | |
void Complete() | |
{ | |
try | |
{ | |
_complete = true; | |
if (_callback != null) | |
{ | |
_callback(this); | |
} | |
lock (this) | |
{ | |
if (_event != null) | |
_event.Set(); | |
} | |
} | |
catch (Exception) | |
{ | |
// this sucks, but what can we do? | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment