Last active
May 13, 2016 09:50
-
-
Save omerfarukz/9460975ba68e0b66f7ab32904c022c35 to your computer and use it in GitHub Desktop.
This file contains 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 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