Skip to content

Instantly share code, notes, and snippets.

@shadeglare
Created August 16, 2013 14:05
Show Gist options
  • Save shadeglare/6250235 to your computer and use it in GitHub Desktop.
Save shadeglare/6250235 to your computer and use it in GitHub Desktop.
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