/// <summary> Adds a method dynamically. </summary> /// /// <param name="typeBuilder"> The type builder. </param> /// <param name="methodName"> Name of the method. </param> /// <param name="dynamicMethodData"> Information describing the dynamic method. </param> private void AddMethodDynamically(TypeBuilder typeBuilder, string methodName, DynamicMethodData dynamicMethodData) { Type[] paramTypes = (dynamicMethodData.Params == null || dynamicMethodData.Params.Length == 0) ? null : dynamicMethodData.Params.Select(t => t.Type).ToArray(); MethodBuilder methodBuilder = typeBuilder.DefineMethod(methodName, MethodAttributes.Public | MethodAttributes.Static, dynamicMethodData.ReturnType, paramTypes); ILGenerator ILout = methodBuilder.GetILGenerator(); int numParams = dynamicMethodData.Params == null ? 0 : dynamicMethodData.Params.Length; for (int i = 0; i < numParams; i++) { var paramAttribute = ParameterAttributes.None; if (dynamicMethodData.Params[i].isIn) { paramAttribute |= ParameterAttributes.In; } if (dynamicMethodData.Params[i].isOut) { paramAttribute |= ParameterAttributes.Out; } methodBuilder.DefineParameter(i + 1, paramAttribute, dynamicMethodData.Params[i].Name.Replace("@", string.Empty)); } for (byte x = 0; x < numParams; x++) { ILout.Emit(OpCodes.Ldarg_S, x); } string methodAction = string.Empty; if (numParams > 1) { for (int y = 0; y < (numParams - 1); y++) { switch (methodAction) { case "A": ILout.Emit(OpCodes.Add); break; case "M": ILout.Emit(OpCodes.Mul); break; default: ILout.Emit(OpCodes.Add); break; } } } ILout.Emit(OpCodes.Ret); AddActionAttribute(methodBuilder); AddFunctionAttribute(methodBuilder, methodName, dynamicMethodData); }
/// <summary> Adds a function attribute. </summary> /// /// <param name="methodBuilder"> The method builder. </param> /// <param name="methodName"> Name of the method. </param> /// <param name="dynamicMethodData"> Information describing the dynamic method. </param> private void AddFunctionAttribute(MethodBuilder methodBuilder, string methodName, DynamicMethodData dynamicMethodData) { Type attrType = typeof(System.Data.Entity.DbFunctionAttribute); var attr = new CustomAttributeBuilder(attrType.GetConstructor( new[] { typeof(string), typeof(string) }), new object[] { dynamicMethodData.Schema, methodName }); methodBuilder.SetCustomAttribute(attr); }
/// <summary> Adds the actions to model. </summary> /// /// <param name="modelBuilder"> The builder that defines the model for the context being /// created. </param> /// <param name="schema"> The schema. </param> /// <param name="dynamicClassFactory"> The dynamic class factory. </param> /// /// <returns> A Type. </returns> private static void AddActionsToModel( DbModelBuilder modelBuilder, DatabaseSchema schema, DynamicClassFactory dynamicClassFactory) { foreach (var function in schema.Functions) { try { if (function.ReturnType != null) { var dynamicMethodData = new DynamicMethodData(); dynamicMethodData.FunctionType = FunctionType.ModelDefinedFunction; dynamicMethodData.ReturnType = typeof(Int32); dynamicMethodData.Schema = function.SchemaOwner; if (function.Arguments.Count > 0) { dynamicMethodData.Params = new DynamicParameterData[function.Arguments.Count]; for (int i = 0; i < function.Arguments.Count; i++) { dynamicMethodData.Params[i] = new DynamicParameterData() { Name = function.Arguments[i].Name, Type = function.Arguments[i].DataType.GetNetType(), isIn = function.Arguments[i].In, isOut = function.Arguments[i].Out, Length = function.Arguments[i].Length }; } } _dynamicActionMethods.Add(function.Name, dynamicMethodData); } } catch (Exception exception) { DynamicLogger.Instance.WriteLoggerLogError("AddActionsToModel", exception); } } foreach (var procedure in schema.StoredProcedures) { try { var dynamicMethodData = new DynamicMethodData(); dynamicMethodData.FunctionType = FunctionType.ModelDefinedFunction; dynamicMethodData.ReturnType = typeof(Int32); dynamicMethodData.Schema = procedure.SchemaOwner; if (procedure.Arguments.Count > 0) { dynamicMethodData.Params = new DynamicParameterData[procedure.Arguments.Count]; for (int i = 0; i < procedure.Arguments.Count; i++) { dynamicMethodData.Params[i] = new DynamicParameterData() { Name = procedure.Arguments[i].Name, Type = procedure.Arguments[i].DataType.GetNetType(), isIn = procedure.Arguments[i].In, isOut = procedure.Arguments[i].Out, Length = procedure.Arguments[i].Length }; } } _dynamicActionMethods.Add(procedure.Name, dynamicMethodData); } catch (Exception exception) { DynamicLogger.Instance.WriteLoggerLogError("AddActionsToModel", exception); } } try { _dynamicActions = CreateTypeAction(dynamicClassFactory, "DbActions", _dynamicActionMethods); // https://www.nuget.org/packages/EntityFramework.Functions modelBuilder.AddFunctions(_dynamicActions, false); } catch (Exception exception) { DynamicLogger.Instance.WriteLoggerLogError("AddActionsToModel", exception); } }