Skip to content

Instantly share code, notes, and snippets.

@omerfarukz
Last active May 13, 2016 09:50
Show Gist options
  • Save omerfarukz/9460975ba68e0b66f7ab32904c022c35 to your computer and use it in GitHub Desktop.
Save omerfarukz/9460975ba68e0b66f7ab32904c022c35 to your computer and use it in GitHub Desktop.
using Castle.MicroKernel.Registration;
using Castle.Windsor;
using Newtonsoft.Json;
using System;
using System.Linq;
namespace functionsDemo
{
class Program
{
static void Main(string[] args)
{
BuildContainer();
object obj = new
{
left = 3,
right = 5
};
var currentExecutionContext = new ExecutionContext();
var executionResult = currentExecutionContext.Execute<JsonMessage, JsonMessage>(JsonMessage.Create(obj, "Sum"));
PrintResult(executionResult);
Console.ReadKey();
}
private static void PrintResult(ExecutionResult<JsonMessage> executionResult)
{
if (executionResult == null)
throw new Exception();
if (executionResult.State == ExecutionResultState.OK)
{
Console.WriteLine("EXECUTED");
Console.WriteLine("Message:{0}, ReturnValue:{1}", executionResult.Message, executionResult.Value);
}
else
{
Console.WriteLine("INVALID STATE");
Console.WriteLine(executionResult.Message);
}
}
private static void BuildContainer()
{
Bootstrapper.Instance.Container.Register(Component.For<ILogger>().ImplementedBy<DefaultLogger>());
Bootstrapper.Instance.Container.Register(Component.For<IAuthenticationManager>().ImplementedBy<DefaultAuthenticationManager>());
Bootstrapper.Instance.Container.Register(Component.For<IFunctionContext>().ImplementedBy<DefaultFunctionContext>());
Bootstrapper.Instance.Container.Register(Component.For<MyFunctions>());
}
}
public class Bootstrapper
{
public static Bootstrapper Instance = new Bootstrapper();
public WindsorContainer Container = new WindsorContainer();
}
public class MyFunctions
{
public int Sum(IFunctionContext context, FunctionPatameters.MathFunctionParameter parameter)
{
var logMessage = string.Format("Hello from sum, user is authenticated:{0}", context.IsAuthenticated);
context.Log(logMessage);
return parameter.Left + parameter.Right;
}
public class FunctionPatameters
{
public class MathFunctionParameter
{
public int Left { get; set; }
public int Right { get; set; }
}
}
}
#region Context
public class ExecutionContext : ContextBase
{
public ExecutionContext()
{
Name = "ExecutionContext";
}
public ExecutionResult<TOutput> Execute<TInput, TOutput>(TInput input) where TInput : MessageBase where TOutput : MessageBase
{
try
{
Console.WriteLine("Executing input: {0}", input);
var invocationResult = CallRealMethod<TInput, TOutput>(input);
if (invocationResult == null)
return ExecutionStatusExtensions.ToExecutionResultError<TOutput>(null, "not invoked");
var returnValue = ConvertToOutputValue<TOutput>(invocationResult, MessageFormat.Json);
return returnValue.ToExecutionResultOK();
}
catch (Exception ex)
{
return ex.ToExecutionResultError<TOutput>();
}
}
private TOutput ConvertToOutputValue<TOutput>(object invocationResult, MessageFormat format) where TOutput : MessageBase
{
if (format == MessageFormat.Json)
{
return (TOutput)Convert.ChangeType(JsonMessage.Create(invocationResult, null), typeof(JsonMessage));
}
//todo: else
//todo:throw can not extract value
return null;
}
private object CallRealMethod<TInput, TOutput>(TInput input) where TInput : MessageBase where TOutput : MessageBase
{
var targetMethod = typeof(MyFunctions).GetMethod(input.FunctionName);
var targetMethodParameters = targetMethod.GetParameters();
if (targetMethod == null || targetMethodParameters.Length > 2)
throw new InvalidProgramException("method must contains one or zero parameter");
object objectValue = null;
var functionContext = Bootstrapper.Instance.Container.Resolve<IFunctionContext>();
var myFunctionsInstance = Bootstrapper.Instance.Container.Resolve<MyFunctions>(); // todo:
if (targetMethodParameters.Length == 2)
{
objectValue = GetParameterValue(input, targetMethodParameters[1].ParameterType);
return targetMethod.Invoke(myFunctionsInstance, new object[] { functionContext, objectValue });
}
else
{
return targetMethod.Invoke(myFunctionsInstance, new object[] { functionContext });
}
}
private object GetParameterValue<TInput>(TInput input, Type type) where TInput : MessageBase
{
if (input is JsonMessage)
{
var convertedMessage = Convert.ChangeType(input, typeof(JsonMessage)) as JsonMessage;
if (type == null)
return JsonConvert.DeserializeObject(convertedMessage.Body);
else
return JsonConvert.DeserializeObject(convertedMessage.Body, type);
}
//todo: else
//todo:throw can not extract value
return null;
}
}
public interface IContextBase
{
string Name { get; }
}
public class ContextBase : IContextBase
{
public string Name { get; protected set; }
}
public interface IFunctionContext : IContextBase
{
void Log(string message);
bool IsAuthenticated { get; }
}
public class DefaultFunctionContext : ContextBase, IFunctionContext
{
public ILogger Logger { get; private set; }
public IAuthenticationManager AuthenticationManager { get; private set; }
public DefaultFunctionContext(ILogger logger, IAuthenticationManager authenticationManager)
{
Logger = logger;
AuthenticationManager = authenticationManager;
Name = "_FunctionContext__";
}
public void Log(string message)
{
Logger.Info(message);
}
public bool IsAuthenticated
{
get
{
return AuthenticationManager.IsAuthenticated();
}
}
}
#endregion
#region Message
public class MessageBase
{
public MessageFormat Format { get; set; }
public object Body { get; protected set; }
public string FunctionName { get; set; }
}
public class MessageBase<T> : MessageBase
{
public new T Body { get; protected set; }
}
public enum MessageFormat
{
Unknown = 0,
Raw = 10,
Json = 20,
Xml = 30,
}
public class MessageResult<T> : ExecutionResult<MessageBase<T>>
{
}
public class JsonMessage : MessageBase<string>
{
public JsonMessage()
{
Format = MessageFormat.Json;
}
public static JsonMessage Create(object @object, string functionName)
{
var jsonText = JsonConvert.SerializeObject(@object);
return new JsonMessage() { Body = jsonText, FunctionName = functionName };
}
public override string ToString()
{
return string.Format("Function:{0},Format:{1},Body:{2}", FunctionName, Format, Body);
}
}
public class JsonMessageResult : MessageResult<JsonMessage>
{
}
#endregion
#region ExecutionResult
public static class ExecutionStatusExtensions
{
public static ExecutionResult<T> ToExecutionResult<T>(this T TObject, ExecutionResultState state, string message)
{
return new ExecutionResult<T>() { Value = TObject, Message = message, State = state };
}
public static ExecutionResult<T> ToExecutionResultOK<T>(this T TObject)
{
return ToExecutionResult<T>(TObject, ExecutionResultState.OK, null);
}
public static ExecutionResult<T> ToExecutionResultError<T>(this T TObject, string message)
{
return ToExecutionResult<T>(TObject, ExecutionResultState.Error, message);
}
public static ExecutionResult<T> ToExecutionResultError<T>(this Exception exception)
{
return ToExecutionResult<T>(default(T), ExecutionResultState.Error, exception != null ? exception.ToString() : null);
}
}
public class ExecutionResult
{
public ExecutionResultState State { get; set; }
public string Message { get; set; }
}
public enum ExecutionResultState
{
Unkown = 0,
OK = 10,
Error = 20
}
public class ExecutionResult<T> : ExecutionResult
{
public T Value { get; set; }
public override string ToString()
{
return string.Format("State:{0}, Message:{1}, Value:{2}", State, Message, Value);
}
}
#endregion
#region "Misc"
public interface ILogger
{
void Info(string message);
void Error(string message, Exception exception);
}
public class DefaultLogger : ILogger
{
public void Error(string message, Exception exception)
{
Console.WriteLine("{0}\t{1}\t{2}", "ERROR", message, exception != null ? exception.ToString() : null);
}
public void Info(string message)
{
Console.WriteLine("{0}\t{1}", "INFO", message);
}
}
public interface IAuthenticationManager
{
bool IsAuthenticated();
bool IsInRole(string role);
}
public class DefaultAuthenticationManager : IAuthenticationManager
{
public bool IsAuthenticated()
{
return GetAuthenticationInfoFromCurrentThread().IsAuthenticated;
}
public bool IsInRole(string role)
{
return GetAuthenticationInfoFromCurrentThread().Roles.Contains(role);
}
private AuthenticationInfo GetAuthenticationInfoFromCurrentThread()
{
return new AuthenticationInfo() { IsAnonymous = false, IsAuthenticated = true, Roles = new[] { "proxy_agent", "default_role" }, UserId = Guid.NewGuid().ToString("n") };
}
}
public class AuthenticationInfo
{
public bool IsAuthenticated { get; set; }
public bool IsAnonymous { get; set; }
public string UserId { get; set; }
public string[] Roles { get; set; }
}
#endregion
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment