Created
August 16, 2013 14:05
-
-
Save shadeglare/6250235 to your computer and use it in GitHub Desktop.
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; | |
using System.Threading.Tasks; | |
using System.Diagnostics; | |
public sealed class DistributorOperationInfo | |
{ | |
public Object NativeRequest { get; set; } | |
public Object NativeResponse { get; set; } | |
public String Error { get; set; } | |
} | |
public interface IDistributorClient<out TNativeClient, TCredential> | |
{ | |
TNativeClient NativeClient { get; } | |
TCredential Credential { get; } | |
Task<TResponse> ExecuteOperationAsync<TRequest, TResponse>( | |
Func<TCredential, TRequest, Task<TResponse>> operation, | |
TRequest request); | |
Task<TResponse> ExecuteOperationAsync<TRequest, TResponse, TParam>( | |
Func<TCredential, TRequest, TParam, Task<TResponse>> operation, | |
TRequest request, | |
TParam param = default(TParam)); | |
Task<TResponse> ExecuteOperationAsync<TRequest, TResponse, TParam1, TParam2>( | |
Func<TCredential, TRequest, TParam1, TParam2, Task<TResponse>> operation, | |
TRequest request, | |
TParam1 param1 = default(TParam1), | |
TParam2 param2 = default(TParam2)); | |
TResponse ExecuteOperation<TRequest, TResponse>( | |
Func<TCredential, TRequest, TResponse> operation, | |
TRequest request); | |
TResponse ExecuteOperation<TRequest, TResponse, TParam>( | |
Func<TCredential, TRequest, TParam, TResponse> operation, | |
TRequest request, | |
TParam param = default(TParam)); | |
TResponse ExecuteOperation<TRequest, TResponse, TParam1, TParam2>( | |
Func<TCredential, TRequest, TParam1, TParam2, TResponse> operation, | |
TRequest request, | |
TParam1 param1 = default(TParam1), | |
TParam2 param2 = default(TParam2)); | |
/// <summary> | |
/// This event exposes complex operation info after it's completion. | |
/// </summary> | |
event Action<DistributorOperationInfo> OperationComplete; | |
} | |
// Distributor wrapper client for mock native client. | |
public class DistributorNativeClient : IDistributorClient<NativeClient, NativeClientCredential> | |
{ | |
public NativeClient NativeClient | |
{ | |
get; | |
protected set; | |
} | |
public NativeClientCredential Credential | |
{ | |
get; | |
protected set; | |
} | |
public DistributorNativeClient(NativeClient nativeClient = null, NativeClientCredential credential = null) | |
{ | |
NativeClient = nativeClient ?? new NativeClient(); | |
Credential = credential ?? new NativeClientCredential() { Key = "test" }; | |
} | |
public event Action<DistributorOperationInfo> OperationComplete = (o) => { }; | |
protected virtual void OnOperationComplete(DistributorOperationInfo operationInfo) | |
{ | |
OperationComplete(operationInfo); | |
} | |
public async Task<TResponse> ExecuteOperationAsync<TRequest, TResponse>( | |
Func<NativeClientCredential, TRequest, Task<TResponse>> operation, | |
TRequest request) | |
{ | |
var result = default(TResponse); | |
var error = default(String); | |
try | |
{ | |
result = await operation(Credential, request); | |
} | |
catch (Exception e) | |
{ | |
error = e.ToString(); | |
throw; | |
} | |
finally | |
{ | |
OnOperationComplete(new DistributorOperationInfo | |
{ | |
Error = error, | |
NativeRequest = request, | |
NativeResponse = result, | |
}); | |
} | |
return result; | |
} | |
public async Task<TResponse> ExecuteOperationAsync<TRequest, TResponse, TParam>( | |
Func<NativeClientCredential, TRequest, TParam, Task<TResponse>> operation, | |
TRequest request, | |
TParam param = default(TParam)) | |
{ | |
var result = default(TResponse); | |
var error = default(String); | |
try | |
{ | |
result = await operation(Credential, request, param); | |
} | |
catch (Exception e) | |
{ | |
error = e.ToString(); | |
throw; | |
} | |
finally | |
{ | |
OnOperationComplete(new DistributorOperationInfo | |
{ | |
Error = error, | |
NativeRequest = request, | |
NativeResponse = result, | |
}); | |
} | |
return result; | |
} | |
public async Task<TResponse> ExecuteOperationAsync<TRequest, TResponse, TParam1, TParam2>( | |
Func<NativeClientCredential, TRequest, TParam1, TParam2, Task<TResponse>> operation, | |
TRequest request, | |
TParam1 param1 = default(TParam1), | |
TParam2 param2 = default(TParam2)) | |
{ | |
var result = default(TResponse); | |
var error = default(String); | |
try | |
{ | |
result = await operation(Credential, request, param1, param2); | |
} | |
catch (Exception e) | |
{ | |
error = e.ToString(); | |
throw; | |
} | |
finally | |
{ | |
OnOperationComplete(new DistributorOperationInfo | |
{ | |
Error = error, | |
NativeRequest = request, | |
NativeResponse = result, | |
}); | |
} | |
return result; | |
} | |
public TResponse ExecuteOperation<TRequest, TResponse>( | |
Func<NativeClientCredential, TRequest, TResponse> operation, | |
TRequest request) | |
{ | |
var result = default(TResponse); | |
var error = default(String); | |
try | |
{ | |
result = operation(Credential, request); | |
} | |
catch (Exception e) | |
{ | |
error = e.ToString(); | |
throw; | |
} | |
finally | |
{ | |
OnOperationComplete(new DistributorOperationInfo | |
{ | |
Error = error, | |
NativeRequest = request, | |
NativeResponse = result, | |
}); | |
} | |
return result; | |
} | |
public TResponse ExecuteOperation<TRequest, TResponse, TParam>( | |
Func<NativeClientCredential, TRequest, TParam, TResponse> operation, | |
TRequest request, | |
TParam param = default(TParam)) | |
{ | |
var result = default(TResponse); | |
var error = default(String); | |
try | |
{ | |
result = operation(Credential, request, param); | |
} | |
catch (Exception e) | |
{ | |
error = e.ToString(); | |
throw; | |
} | |
finally | |
{ | |
OnOperationComplete(new DistributorOperationInfo | |
{ | |
Error = error, | |
NativeRequest = request, | |
NativeResponse = result, | |
}); | |
} | |
return result; | |
} | |
public TResponse ExecuteOperation<TRequest, TResponse, TParam1, TParam2>( | |
Func<NativeClientCredential, TRequest, TParam1, TParam2, TResponse> operation, | |
TRequest request, | |
TParam1 param1 = default(TParam1), | |
TParam2 param2 = default(TParam2)) | |
{ | |
var result = default(TResponse); | |
var error = default(String); | |
try | |
{ | |
result = operation(Credential, request, param1, param2); | |
} | |
catch (Exception e) | |
{ | |
error = e.ToString(); | |
throw; | |
} | |
finally | |
{ | |
OnOperationComplete(new DistributorOperationInfo | |
{ | |
Error = error, | |
NativeRequest = request, | |
NativeResponse = result, | |
}); | |
} | |
return result; | |
} | |
} | |
// Mock native client credential | |
public sealed class NativeClientCredential | |
{ | |
public String Key { get; set; } | |
} | |
// Mock native client | |
public sealed class NativeClient | |
{ | |
//Emulates long task. | |
public async Task<Int32> CalculateFactorialAsync(NativeClientCredential credential, Int32 number) | |
{ | |
CheckCredential(credential); | |
var task = Task.Factory.StartNew<Int32>(() => | |
{ | |
Thread.Sleep(20); | |
var result = 1; | |
if (number >= 22) | |
{ | |
throw new ArgumentException(); | |
} | |
if (number != 0 && number != 1) | |
{ | |
for (var i = 2; i <= number; i++) | |
{ | |
result *= i; | |
} | |
} | |
return result; | |
}); | |
return await task; | |
} | |
public Int32 CalculateFactorial(NativeClientCredential credential, Int32 number) | |
{ | |
CheckCredential(credential); | |
Thread.Sleep(20); | |
var result = 1; | |
if (number >= 22) | |
{ | |
throw new ArgumentException(); | |
} | |
if (number != 0 && number != 1) | |
{ | |
for (var i = 2; i <= number; i++) | |
{ | |
result *= i; | |
} | |
} | |
return result; | |
} | |
public Int32 CalculateSum(NativeClientCredential credential, Int32 a, Int32 b) | |
{ | |
CheckCredential(credential); | |
return a + b; | |
} | |
private void CheckCredential(NativeClientCredential credential) | |
{ | |
if (credential.Key != "test") | |
{ | |
throw new InvalidOperationException(); | |
} | |
} | |
} | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
var nativeClient = new NativeClient(); | |
var distributorClient = new DistributorNativeClient(nativeClient); | |
distributorClient.OperationComplete += OperationCompleteCallback; | |
distributorClient.ExecuteOperation<Int32, Int32, Int32>(distributorClient.NativeClient.CalculateSum, 5); | |
var stopwatch = new Stopwatch(); | |
stopwatch.Start(); | |
for (var i = 0; i < 1000; i++) | |
{ | |
var task = distributorClient.ExecuteOperationAsync(distributorClient.NativeClient.CalculateFactorialAsync, 5); | |
var result = task.Result; | |
} | |
stopwatch.Stop(); | |
Console.WriteLine(stopwatch.ElapsedMilliseconds); | |
stopwatch.Restart(); | |
for (var i = 0; i < 1000; i++) | |
{ | |
var result = distributorClient.ExecuteOperation(distributorClient.NativeClient.CalculateFactorial, 5); | |
} | |
stopwatch.Stop(); | |
Console.WriteLine(stopwatch.ElapsedMilliseconds); | |
} | |
public static void OperationCompleteCallback(DistributorOperationInfo operationInfo) | |
{ | |
//My be a logging operations. | |
//Console.WriteLine(operationInfo.ToJson()); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment