public static IDictionary <Guid, ISysComponent> ParseConfig(String jsonString) { Dictionary <Guid, ISysComponent> result = new Dictionary <Guid, ISysComponent>(); dynamic jsonObject = JValue.Parse(jsonString); foreach (JObject j in jsonObject as JArray) { ModelConfig model = j.ToObject <ModelConfig>(); ISysComponent component = null; if (!VerifyModel(model)) { //Throw error? continue; } if (!Caches.Interfaces.TryGetValue(model.Interface.ToLower(), out Type Interface)) { //Do error handling continue; } //Generic implementation of ISysComponent component = new SysComponent(model.Id, model.Name); component.LoadComponent(model.Type, model.Data); //Dynamic interface implementation var newType = DRII.DynamicInterfaceImplementation(Interface, (SysComponent)component); if (newType is ISysComponent comp) { result.Add(comp.Id, comp); } } return(result); }
/// <summary> /// Merge the source property values with the new type instance /// </summary> /// <typeparam name="K"> Type of the new type</typeparam> /// <param name="source">The source instance to be copied from</param> /// <param name="destination">The new type instance</param> /// <returns></returns> private static K BindToInstance <K>(SysComponent source, K destination) { foreach (PropertyInfo property in source.GetType().GetProperties(visibilityFlags)) { var prop = destination.GetType().GetProperty(property.Name, visibilityFlags); if (prop != null && prop.CanWrite) { prop.SetValue(destination, property.GetValue(source), null); } } return(destination); }
/// <summary> /// Generates a list of generically generated delegates, to be used in the constructor for instancing /// the dynamically generated type /// </summary> /// <param name="delegates">List of previously specified delegates</param> /// <param name="source">The source containing the model instance</param> /// <param name="newType">Referance for the dynamically generated type</param> /// <returns></returns> private static List <dynamic> GenerateParameters(List <TypeHelper> delegates, SysComponent source, ref Type newType) { List <dynamic> ctrList = new List <dynamic>(); foreach (var d in delegates) { //Name of the method var name = d.MethodName; //Method reference in the new type var method = newType.GetMethod(name); //Parameters of newType method var methodParameters = method.GetParameters(); //Found method in the model instance, //currently not used as the method in newtype has the same signature and name. MethodInfo InstanceMethod = source.Instance.GetType().GetMethod(name); //TODO:search algorithm if (InstanceMethod == null) { if (name.StartsWith("get_".ToLower())) { var split = name.Split('_'); var filteredName = split[1]; InstanceMethod = source.Instance.GetType().GetMethod(filteredName); if (method == null) { InstanceMethod = MethodDiscovery(source.Instance.GetType(), d); } } } var methodReturnType = method.ReturnType; List <Type> parameters = new List <Type>(); Type delType; foreach (var m in methodParameters) { parameters.Add(m.ParameterType); } if (methodReturnType == typeof(void)) { delType = Expression.GetActionType(parameters.ToArray()); } else { parameters.Add(methodReturnType); delType = Expression.GetFuncType(parameters.ToArray()); } Delegate deli = Delegate.CreateDelegate(delType, source.Instance, name); ctrList.Add(deli); } return(ctrList); }
/// <summary> /// Implements the specified Interface on a given SysComponent source. Outputs the instanced type /// with properties copied from the specified source /// </summary> /// <param name="Interface">Interface Type parameter, can be inherited type</param> /// <param name="source">The instance containing the loaded model</param> /// <returns></returns> public static object DynamicInterfaceImplementation(Type Interface, SysComponent source) { Type newType = null; //Try to retrieve earlier implementation of the specified interface if (Implementations.TryGetValue(Interface, out newType)) { //Retrieve constructor parameters to be used in the new type instance if (Parameters.TryGetValue(newType, out List <TypeHelper> parameters)) { } //Instantiate the new type, using the results from GenerateParameters with the found constructor //GenerateParameters returns a List of delegates, used to bind methods to the model. var instance = Activator.CreateInstance(newType, GenerateParameters(parameters, source, ref newType).ToArray()); if (source == null) { return(instance); } else { return(BindToInstance(source, (ISysComponent)instance)); } } else { var name = Guid.NewGuid().ToString(); AssemblyBuilder assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName(name), AssemblyBuilderAccess.Run); ModuleBuilder module = assembly.DefineDynamicModule(name); TypeBuilder type = module.DefineType(typeof(SysComponent).Name + "_" + Interface.Name, TypeAttributes.Public, typeof(SysComponent)); ConstructorBuilder cstrBuilder = type.DefineConstructor(MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, CallingConventions.Standard, GetConstructorParams(Interface)); var cstrGenerator = cstrBuilder.GetILGenerator(); //Load "This" instance reference cstrGenerator.Emit(OpCodes.Ldarg_0); //Call the default constructor for the type cstrGenerator.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes)); var fieldsList = new List <string>(); var paramList = new List <TypeHelper>(); Type[] interfaces = Interface.GetInterfaces(); var index = 0; foreach (var ancestor in interfaces) { ImplementInterface(ancestor, ref fieldsList, ref type, ref cstrBuilder, ref cstrGenerator, ref paramList, ref index); } ImplementInterface(Interface, ref fieldsList, ref type, ref cstrBuilder, ref cstrGenerator, ref paramList, ref index); //Return from the constructor cstrGenerator.Emit(OpCodes.Ret); newType = type.CreateType(); Implementations.Add(Interface, newType); Parameters.Add(newType, paramList); var parameterList = new List <dynamic>(); parameterList = GenerateParameters(paramList, source, ref newType); var instance = Activator.CreateInstance(newType, parameterList.ToArray()); if (source == null) { return(instance); } else { return(BindToInstance(source, (ISysComponent)instance)); //return BindToInstance(Interface, ret); } } }