/// <summary> /// An attribute builder method /// </summary> /// <param name="attr"></param> /// <returns></returns> public static CustomAttributeBuilder GetCustomAttributeBuilder(SWParameterAttribute attr) { string name = attr.m_name; Type[] arrParamTypes = new Type[] { typeof(string), typeof(SqlDbType), typeof(int), typeof(byte), typeof(byte), typeof(object), typeof(SWParameterType) }; object[] arrParamValues = new object[] { name, attr.m_sqlDbType, attr.m_size, attr.m_precision, attr.m_scale, attr.m_treatAsNull, attr.m_parameterType }; ConstructorInfo ctor = typeof(SWParameterAttribute).GetConstructor(arrParamTypes); return(new CustomAttributeBuilder(ctor, arrParamValues)); }
/// <summary> /// Adds attributes and an implementation to a method of the created class. /// </summary> /// <param name="method">MethodInfo object.</param> /// <param name="tb">Type builder object.</param> private static void AddMethodImplementation(MethodInfo method, TypeBuilder tb) { // get method return type Type RetType = method.ReturnType; // get method paramete information ParameterInfo [] prms = method.GetParameters(); int paramCount = prms.Length; // get method parameter types and names Type [] paramTypes = new Type [paramCount]; string[] paramNames = new string[paramCount]; ParameterAttributes[] paramAttrs = new ParameterAttributes[paramCount]; for (int i = 0; i < paramCount; ++i) { paramTypes[i] = prms[i].ParameterType; paramNames[i] = prms[i].Name; paramAttrs[i] = prms[i].Attributes; } // define method body MethodBuilder methodBody = tb.DefineMethod(method.Name, MethodAttributes.Public | MethodAttributes.Virtual, method.ReturnType, paramTypes); // define method attribute if exists SWCommandAttribute CommandMethodAttr = (SWCommandAttribute)Attribute.GetCustomAttribute(method, typeof(SWCommandAttribute)); if (CommandMethodAttr != null) { methodBody.SetCustomAttribute(SWCommandAttribute.GetCustomAttributeBuilder(CommandMethodAttr)); } // define method parameters with their attributes for (int i = 0; i < paramCount; ++i) { ParameterBuilder param = methodBody.DefineParameter(i + 1, paramAttrs[i], paramNames[i]); SWParameterAttribute[] ParameterAttr = (SWParameterAttribute[])prms[i].GetCustomAttributes(typeof(SWParameterAttribute), false); if (ParameterAttr.Length > 0) { param.SetCustomAttribute(SWParameterAttribute.GetCustomAttributeBuilder(ParameterAttr[0])); } } // generate method body GenerateMethodBody(methodBody.GetILGenerator(), RetType, prms); }
/// <summary> /// An attribute builder method /// </summary> /// <param name="attr"></param> /// <returns></returns> public static CustomAttributeBuilder GetCustomAttributeBuilder(SWParameterAttribute attr) { string name = attr.m_name; Type[] arrParamTypes = new Type[] {typeof(string), typeof(SqlDbType), typeof(int), typeof(byte), typeof(byte), typeof(object), typeof(SWParameterType)}; object[] arrParamValues = new object[] {name, attr.m_sqlDbType, attr.m_size, attr.m_precision, attr.m_scale, attr.m_treatAsNull, attr.m_parameterType}; ConstructorInfo ctor = typeof(SWParameterAttribute).GetConstructor(arrParamTypes); return new CustomAttributeBuilder(ctor, arrParamValues); }
/// <summary> /// Generates command parameters. /// For some command types the command text can be changed during parameter generating. /// </summary> /// <param name="command">Command object.</param> /// <param name="method"><see cref="MethodInfo"/> type object</param> /// <param name="values">Array of values for the command parameters.</param> /// <param name="swCommandType"><see cref="SWCommandType"/> enumeration value</param> /// <param name="indexes">Array of parameter indices.</param> private static void GenerateCommandParameters(DbCommand command, MethodInfo method, object[] values, int[] indexes, SWCommandType swCommandType) { #region InsertUpdate parts declaration string sUpdatePart1 = ""; string sUpdatePart2 = ""; string sUpdate = ""; string sInsertPart1 = ""; string sInsertPart2 = ""; string sInsert = ""; string sAutoincrementColumnName = ""; #endregion //DatabaseHelper db = new DatabaseHelper(); ParameterInfo[] methodParameters = method.GetParameters(); int sqlParamIndex = 0; for (int paramIndex = 0; paramIndex < methodParameters.Length; ++paramIndex) { indexes[paramIndex] = -1; ParameterInfo paramInfo = methodParameters[paramIndex]; // create command parameter DbParameter sqlParameter = command.CreateParameter(); // set default values string paramName = paramInfo.Name; SWParameterType paramCustType = SWParameterType.Default; object v = values[paramIndex]; // get parameter attribute and set command parameter settings SWParameterAttribute paramAttribute = (SWParameterAttribute)Attribute.GetCustomAttribute(paramInfo, typeof(SWParameterAttribute)); if (paramAttribute != null) { paramCustType = paramAttribute.ParameterType; if (paramAttribute.IsNameDefined) { paramName = sqlParameter.ParameterName; } if (paramAttribute.IsTypeDefined) { sqlParameter.DbType = (DbType)paramAttribute.SqlDbType; } if (paramAttribute.IsSizeDefined) { sqlParameter.Size = paramAttribute.Size; } //if (paramAttribute.IsScaleDefined) // sqlParameter.Scale = paramAttribute.Scale; //if (paramAttribute.IsPrecisionDefined) // sqlParameter..Precision = paramAttribute.Precision; if (CompareTreatAsNullValues(paramAttribute.TreatAsNull, v, paramInfo.ParameterType)) { v = DBNull.Value; } } // parameter direction if (paramCustType == SWParameterType.SPReturnValue) { sqlParameter.Direction = ParameterDirection.ReturnValue; sqlParameter.DbType = DbType.Int32; } else if (paramInfo.ParameterType.IsByRef) { sqlParameter.Direction = paramInfo.IsOut ? ParameterDirection.Output : ParameterDirection.InputOutput; } else { sqlParameter.Direction = ParameterDirection.Input; } // generate parts of InsertUpdate expresion #region generate parts of InsertUpdate expresion if (paramCustType == SWParameterType.Identity) { if (sAutoincrementColumnName.Length > 0) { throw new SqlWrapperException("Only one identity parameter is possible"); } sAutoincrementColumnName = paramName; Type reftype = GetRefType(paramInfo.ParameterType); if (reftype == null) { throw new SqlWrapperException("Identity parameter must be ByRef parameter"); } // check default value if (paramAttribute.TreatAsNull.ToString() == SWParameterAttribute.NullReturnValueToken) { if (Convert.ToInt64(v) <= 0) { v = DBNull.Value; } } } if (swCommandType == SWCommandType.InsertUpdate) { string fieldName = "[" + paramName + "]"; string cmdparamName = "@" + paramName; if (paramCustType != SWParameterType.Identity) { sInsertPart1 = AddWithDelim(sInsertPart1, ", ", fieldName); sInsertPart2 = AddWithDelim(sInsertPart2, ", ", cmdparamName); } if ((paramCustType == SWParameterType.Key) || (paramCustType == SWParameterType.Identity)) { sUpdatePart2 = AddWithDelim(sUpdatePart2, " and ", fieldName + "=" + cmdparamName); } if (paramCustType != SWParameterType.Identity) { sUpdatePart1 = AddWithDelim(sUpdatePart1, ", ", fieldName + "=" + cmdparamName); } } #endregion // set parameter name sqlParameter.ParameterName = "@" + paramName; // set parameter value if (v == null) { v = DBNull.Value; } sqlParameter.Value = values[paramIndex]; // this is to set a proper data type sqlParameter.Value = v; // add parameter to the command object command.Parameters.Add(sqlParameter); indexes[paramIndex] = sqlParamIndex; sqlParamIndex++; } // in case of InsertUpdate command type compile new command text #region generate InsertUpdate expresion if (swCommandType == SWCommandType.InsertUpdate) { string TableName = command.CommandText; string CommandText = ""; if (sUpdatePart2 == "") { throw new SqlWrapperException("No Identity or Autoincrement field is defined."); } sInsert = String.Format(" insert into [{0}]({1}) values({2}) ", TableName, sInsertPart1, sInsertPart2); sUpdate = String.Format(" update [{0}] set {1} where {2} ", TableName, sUpdatePart1, sUpdatePart2); if (sAutoincrementColumnName == "") { CommandText += String.Format("{0} if (@@rowcount = 0) {1}", sUpdate, sInsert); } else { CommandText += String.Format("if(@{0} is NULL) begin {1} select @{0} = SCOPE_IDENTITY() end ", sAutoincrementColumnName, sInsert); CommandText += String.Format("else begin {0} end", sUpdate); } command.CommandText = CommandText; } #endregion }