Mercurial > pub > bltoolkit
view Source/DataAccess/DataAccessorBuilder.cs @ 9:1e85f66cf767 default tip
update bltoolkit
author | nickolay |
---|---|
date | Thu, 05 Apr 2018 20:53:26 +0300 |
parents | f990fcb411a9 |
children |
line wrap: on
line source
using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Linq; using System.Reflection; using System.Reflection.Emit; using BLToolkit.Common; using BLToolkit.Data; using BLToolkit.Data.DataProvider; using BLToolkit.Mapping; using BLToolkit.Properties; using BLToolkit.Reflection; using BLToolkit.Reflection.Emit; using BLToolkit.TypeBuilder; using BLToolkit.TypeBuilder.Builders; namespace BLToolkit.DataAccess { public class DataAccessorBuilder : AbstractTypeBuilderBase { struct MapOutputParametersValue { public readonly string ReturnValueMember; public readonly ParameterInfo ParameterInfo; public MapOutputParametersValue(string returnValueMember, ParameterInfo parameterInfo) { ReturnValueMember = returnValueMember; ParameterInfo = parameterInfo; } } public override int GetPriority(BuildContext context) { return TypeBuilderConsts.Priority.DataAccessor; } public override bool IsApplied(BuildContext context, AbstractTypeBuilderList builders) { if (context.IsBuildStep) { if (context.IsAbstractMethod) { // Give up if there is any builder that builds the method body. // if (builders.Count > 1) foreach (IAbstractTypeBuilder builder in builders) if (builder != this && builder.IsApplied(context, builders)) return false; return true; } // Treat an abstract getter/setter as a regular method // when the property has [NoInstance] attribute // if (context.IsAbstractGetter || context.IsAbstractSetter) return context.CurrentProperty.IsDefined(typeof(NoInstanceAttribute), true); } return false; } private Dictionary<Type, Type> _actualTypes; private Dictionary<Type, Type> ActualTypes { get { if (_actualTypes == null) { _actualTypes = new Dictionary<Type, Type>(); object[] attrs = Context.Type.GetAttributes(typeof(ActualTypeAttribute)); foreach (ActualTypeAttribute attr in attrs) if (!_actualTypes.ContainsKey(attr.BaseType)) _actualTypes.Add(attr.BaseType, attr.ActualType); } return _actualTypes; } } enum ReturnType { DataReader, DataSet, DataTable, List, Dictionary, Enumerable, Void, Scalar, Object } static ReturnType GetReturnType(Type returnType) { if (returnType == typeof(IDataReader)) return ReturnType.DataReader; if (returnType == typeof(DataSet) || returnType.IsSubclassOf(typeof(DataSet))) return ReturnType.DataSet; if (returnType == typeof(DataTable) || returnType.IsSubclassOf(typeof(DataTable))) return ReturnType.DataTable; if (!returnType.IsArray && (IsInterfaceOf(returnType, typeof(IList)) || returnType.IsGenericType && returnType.GetGenericTypeDefinition() == typeof(IList<>))) return ReturnType.List; if (IsInterfaceOf(returnType, typeof(IDictionary)) || returnType.IsGenericType && returnType.GetGenericTypeDefinition() == typeof(IDictionary<,>)) return ReturnType.Dictionary; if (returnType == typeof(IEnumerable) || returnType.IsGenericType && returnType.GetGenericTypeDefinition() == typeof(IEnumerable<>)) return ReturnType.Enumerable; if (returnType == typeof(void)) return ReturnType.Void; if (TypeHelper.IsScalar(returnType.IsByRef ? returnType.GetElementType() : returnType)) return ReturnType.Scalar; return ReturnType.Object; } void ThrowTypeBuilderException(string message) { throw new TypeBuilderException( string.Format(message, Context.CurrentMethod.DeclaringType.Name, Context.CurrentMethod.Name)); } const BindingFlags _bindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; readonly Type _baseType = typeof(DataAccessor); Type _objectType; bool _explicitObjectType; ParameterInfo[] _parameters; ArrayList _paramList; ArrayList _refParamList; bool _createManager; LocalBuilder _locManager; LocalBuilder _locObjType; ArrayList _outputParameters; SqlQueryAttribute _sqlQueryAttribute; ArrayList _formatParamList; ParameterInfo _destination; ArrayList _mapOutputParameters; protected override void BuildAbstractMethod() { // Any class variable must be initialized before use // as the same instance of the class is utilized to build abstract methods. // _paramList = new ArrayList(); _refParamList = new ArrayList(); _formatParamList = new ArrayList(); _mapOutputParameters = new ArrayList(); _destination = null; _createManager = true; _objectType = null; _explicitObjectType = false; _parameters = Context.CurrentMethod.GetParameters(); _locManager = Context.MethodBuilder.Emitter.DeclareLocal(typeof(DbManager)); _locObjType = Context.MethodBuilder.Emitter.DeclareLocal(typeof(Type)); _outputParameters = null; _sqlQueryAttribute = null; GetSqlQueryAttribute(); ProcessParameters(); var returnType = MethodReturnType; var rt = GetReturnType(returnType); CreateDbManager(rt != ReturnType.Enumerable); SetObjectType(); // Define execution method type. // switch (rt) { case ReturnType.DataReader : ExecuteReader(); break; case ReturnType.DataSet : ExecuteDataSet(returnType); break; case ReturnType.DataTable : ExecuteDataTable(); break; case ReturnType.Void : ExecuteNonQuery(); break; case ReturnType.Scalar : ExecuteScalar(); break; case ReturnType.Enumerable : ExecuteEnumerable(); break; case ReturnType.List: if (!_explicitObjectType) { Type elementType = TypeHelper.GetListItemType(returnType); if (elementType == typeof(object) && _destination != null) elementType = TypeHelper.GetListItemType(Context.CurrentMethod.ReturnType); if (elementType != typeof(object)) _objectType = elementType; if (ActualTypes.ContainsKey(_objectType)) _objectType = ActualTypes[_objectType]; } if (_objectType == null || _objectType == typeof(object)) ThrowTypeBuilderException(Resources.DataAccessorBuilder_BadListItemType); if (TypeHelper.IsScalar(_objectType)) ExecuteScalarList(); else ExecuteList(); break; case ReturnType.Dictionary: { Type elementType = null; Type keyType = typeof(object); Type[] gTypes = TypeHelper.GetGenericArguments(returnType, typeof(IDictionary)); if ((gTypes == null || gTypes.Length != 2) && _destination != null) gTypes = TypeHelper.GetGenericArguments(_destination.ParameterType, typeof(IDictionary)); if (gTypes != null && gTypes.Length == 2) { keyType = gTypes[0]; elementType = gTypes[1]; } if (elementType == null || _explicitObjectType) elementType = _objectType; if (elementType == null || elementType == typeof(object)) ThrowTypeBuilderException(Resources.DataAccessorBuilder_BadListItemType); bool isIndex = TypeHelper.IsSameOrParent(typeof(CompoundValue), keyType); if (keyType != typeof(object) && !isIndex && !TypeHelper.IsScalar(keyType)) ThrowTypeBuilderException( Resources.DataAccessorBuilder_BadKeyType); MethodInfo mi = Context.CurrentMethod; object[] attrs = mi.GetCustomAttributes(typeof(IndexAttribute), true); NameOrIndexParameter[] fields = new NameOrIndexParameter[0]; if (attrs.Length != 0) fields = ((IndexAttribute)attrs[0]).Fields; if (fields.Length > 1 && keyType != typeof(object) && !isIndex) ThrowTypeBuilderException( Resources.DataAccessor_InvalidKeyType); if (TypeHelper.IsScalar(elementType)) { attrs = mi.GetCustomAttributes(typeof(ScalarFieldNameAttribute), true); if (attrs.Length == 0) ThrowTypeBuilderException(Resources.DataAccessorBuilder_ScalarFieldNameMissing); NameOrIndexParameter scalarField = ((ScalarFieldNameAttribute)attrs[0]).NameOrIndex; if (fields.Length == 0) ExecuteScalarDictionaryWithPK(keyType, scalarField, elementType); else if (isIndex || fields.Length > 1) ExecuteScalarDictionaryWithMapIndex(fields, scalarField, elementType); else ExecuteScalarDictionaryWithScalarKey(fields[0], keyType, scalarField, elementType); } else { if (!_explicitObjectType && ActualTypes.ContainsKey(elementType)) elementType = ActualTypes[elementType]; if (fields.Length == 0) ExecuteDictionaryWithPK(keyType, elementType); else if (isIndex || fields.Length > 1) ExecuteDictionaryWithMapIndex(fields, elementType); else ExecuteDictionaryWithScalarKey(fields[0], elementType); } } break; default: if (_objectType == null || !TypeHelper.IsSameOrParent(returnType, _objectType)) _objectType = returnType; if (!_explicitObjectType && ActualTypes.ContainsKey(_objectType)) _objectType = ActualTypes[_objectType]; ExecuteObject(); break; } GetOutRefParameters(); if (rt != ReturnType.Enumerable) Finally(); } protected override void BuildAbstractGetter() { BuildAbstractMethod(); } protected override void BuildAbstractSetter() { BuildAbstractMethod(); } void GetSqlQueryAttribute() { object[] attrs = Context.CurrentMethod.GetCustomAttributes(typeof(SqlQueryAttribute), true); if (attrs.Length != 0) _sqlQueryAttribute = (SqlQueryAttribute)attrs[0]; } void AddParameter(ParameterInfo pi) { Type pType = pi.ParameterType; if (pType.IsByRef) pType = pType.GetElementType(); if (TypeHelper.IsScalar(pType) #if FW4 || pi.IsRefCursor() #endif ) _paramList.Add(pi); else if (pType == typeof(DbManager) || pType.IsSubclassOf(typeof(DbManager))) _createManager = false; else _refParamList.Add(pi); } void ProcessParameters() { for (int i = 0; i < _parameters.Length; i++) { ParameterInfo pi = _parameters[i]; NoMapAttribute[] attrs = (NoMapAttribute[])pi.GetCustomAttributes(typeof(NoMapAttribute), true); if (attrs.Length == 0) AddParameter(pi); else { for (int j = 0; j < attrs.Length; ++j) { if (!attrs[j].NoMap) AddParameter(pi); if (attrs[j] is FormatAttribute) { int index = ((FormatAttribute)attrs[j]).Index; if (index < 0) index = 0; else if (index > _formatParamList.Count) index = _formatParamList.Count; _formatParamList.Insert(index, pi); } else if (attrs[j] is DestinationAttribute) { if (_destination != null) throw new TypeBuilderException(Resources.DataAccessorBuilderTooManyDestinations); _destination = pi; } } } } } void CreateDbManager(bool beginException) { EmitHelper emit = Context.MethodBuilder.Emitter; if (_createManager) { emit .ldarg_0 .callvirt(_baseType, "GetDbManager") .stloc(_locManager); if (beginException) emit.BeginExceptionBlock(); } else { for (int i = 0; i < _parameters.Length; i++) { Type pType = _parameters[i].ParameterType; if (pType == typeof(DbManager) || pType.IsSubclassOf(typeof(DbManager))) { emit .ldarg(_parameters[i]) .stloc(_locManager) ; break; } } } } void SetObjectType() { var mi = Context.CurrentMethod; var attrs = mi.GetCustomAttributes(typeof(ObjectTypeAttribute), true); if (attrs.Length == 0) attrs = mi.DeclaringType.GetCustomAttributes(typeof(ObjectTypeAttribute), true); else _explicitObjectType = true; if (attrs.Length != 0) _objectType = ((ObjectTypeAttribute)attrs[0]).ObjectType; if (_objectType == null) { var types = TypeHelper.GetGenericArguments(mi.DeclaringType, typeof(DataAccessor)); if (types != null) _objectType = types[0]; } } #region ExecuteReader void ExecuteReader() { InitObjectType(); GetSprocNameOrSqlQueryTest(); CallSetCommand(); var attrs = Context.CurrentMethod.GetCustomAttributes(typeof(CommandBehaviorAttribute), true); if (attrs.Length == 0) { Context.MethodBuilder.Emitter .callvirt(typeof(DbManager).GetMethod("ExecuteReader", Type.EmptyTypes)) .stloc(Context.ReturnValue) ; } else { Context.MethodBuilder.Emitter .ldc_i4_((int)((CommandBehaviorAttribute)attrs[0]).CommandBehavior) .callvirt(typeof(DbManager), "ExecuteReader", typeof(CommandBehavior)) .stloc(Context.ReturnValue) ; } } #endregion #region ExecuteDataSet void ExecuteDataSet(Type returnType) { CreateReturnTypeInstance(); InitObjectType(); GetSprocNameOrSqlQueryTest(); CallSetCommand(); var emit = Context.MethodBuilder.Emitter; if (returnType == typeof(DataSet)) { LoadDestinationOrReturnValue(); object[] attrs = Context.CurrentMethod.GetCustomAttributes(typeof(DataSetTableAttribute), true); if (attrs.Length == 0) { emit .callvirt(typeof(DbManager), "ExecuteDataSet", typeof(DataSet)) .pop .end() ; } else { emit .ldNameOrIndex(((DataSetTableAttribute)attrs[0]).NameOrIndex) .callvirt(typeof(DbManager), "ExecuteDataSet", typeof(DataSet), typeof(NameOrIndexParameter)) .pop .end() ; } } else { emit .pop .end() ; LoadDestinationOrReturnValue(); Label l1 = emit.DefineLabel(); Label l2 = emit.DefineLabel(); emit .callvirt(typeof(DataSet).GetProperty("Tables").GetGetMethod()) .callvirt(typeof(InternalDataCollectionBase).GetProperty("Count").GetGetMethod()) .ldc_i4_0 .ble_s(l1) .ldloc(_locManager); LoadDestinationOrReturnValue(); object[] attrs = Context.CurrentMethod.GetCustomAttributes(typeof(DataSetTableAttribute), true); if (attrs.Length == 0) { LoadDestinationOrReturnValue(); emit .callvirt(typeof(DataSet).GetProperty("Tables").GetGetMethod()) .ldc_i4_0 .callvirt(typeof(DataTableCollection), "get_Item", typeof(int)) .callvirt(typeof(DataTable).GetProperty("TableName").GetGetMethod()) .call(typeof(NameOrIndexParameter), "op_Implicit", typeof(string)) ; } else { emit .ldNameOrIndex(((DataSetTableAttribute)attrs[0]).NameOrIndex) ; } emit .callvirt(typeof(DbManager), "ExecuteDataSet", typeof(DataSet), typeof(NameOrIndexParameter)) .pop .br_s(l2) .MarkLabel(l1) .ldloc(_locManager); LoadDestinationOrReturnValue(); emit .callvirt(typeof(DbManager), "ExecuteDataSet", typeof(DataSet)) .pop .MarkLabel(l2) ; } } #endregion #region ExecuteDataTable void ExecuteDataTable() { CreateReturnTypeInstance(); InitObjectType(); GetSprocNameOrSqlQueryTest(); CallSetCommand(); LoadDestinationOrReturnValue(); EmitHelper emit = Context.MethodBuilder.Emitter; emit .callvirt(typeof(DbManager), "ExecuteDataTable", typeof(DataTable)) .pop .end() ; // When DataSetTableAttribute is present, simply set table name to the name specified. // object[] attrs = Context.CurrentMethod.GetCustomAttributes(typeof(DataSetTableAttribute), true); if (attrs.Length != 0) { DataSetTableAttribute attr = (DataSetTableAttribute)attrs[0]; if (!attr.NameOrIndex.ByName) throw new TypeBuilderException(string.Format( Resources.DataAccessorBuilder_DataSetTableMustBeByName, Context.CurrentMethod.DeclaringType.Name, Context.CurrentMethod.Name)); LoadDestinationOrReturnValue(); emit .ldstr(attr.NameOrIndex.Name) .callvirt(typeof(DataTable), "set_TableName", typeof(string)) ; } } #endregion #region ExecuteScalarList void ExecuteScalarList() { CreateReturnTypeInstance(); InitObjectType(); GetSprocNameOrSqlQueryTest(); CallSetCommand(); LoadDestinationOrReturnValue(); object[] attrs = Context.CurrentMethod.GetCustomAttributes(typeof(ScalarFieldNameAttribute), true); if (attrs.Length == 0) { Context.MethodBuilder.Emitter .ldloc(_locObjType) .callvirt(typeof(DbManager), "ExecuteScalarList", typeof(IList), typeof(Type)) .pop .end() ; } else { Context.MethodBuilder.Emitter .ldloc(_locObjType) .ldNameOrIndex(((ScalarFieldNameAttribute)attrs[0]).NameOrIndex) .callvirt(typeof(DbManager), "ExecuteScalarList", typeof(IList), typeof(Type), typeof(NameOrIndexParameter)) .pop .end() ; } } void ExecuteList() { CreateReturnTypeInstance(); InitObjectType(); GetSprocNameOrSqlQueryTest(); CallSetCommand(); LoadDestinationOrReturnValue(); Context.MethodBuilder.Emitter .CastIfNecessary(typeof(IList), MethodReturnType) .ldloc(_locObjType) .callvirt(typeof(DbManager), "ExecuteList", typeof(IList), typeof(Type)) .pop .end() ; } #endregion #region ExecuteDictionary public FieldBuilder GetIndexField(NameOrIndexParameter[] namesOrIndexes) { var id = "index$" + string.Join("%", Array.ConvertAll<NameOrIndexParameter, string>(namesOrIndexes, delegate(NameOrIndexParameter nameOrIndex) { return nameOrIndex.ToString(); })); var fieldBuilder = Context.GetField(id); if (fieldBuilder == null) { fieldBuilder = Context.CreatePrivateStaticField(id, typeof(MapIndex)); EmitHelper emit = Context.TypeBuilder.TypeInitializer.Emitter; emit .ldc_i4_(namesOrIndexes.Length) .newarr(typeof(NameOrIndexParameter)) ; for (int i = 0; i < namesOrIndexes.Length; i++) { emit .dup .ldc_i4_(i) .ldelema(typeof(NameOrIndexParameter)); if (namesOrIndexes[i].ByName) { emit .ldstr(namesOrIndexes[i].Name) .call(typeof(NameOrIndexParameter), "op_Implicit", typeof(string)); } else { emit .ldc_i4_(namesOrIndexes[i].Index) .call(typeof(NameOrIndexParameter), "op_Implicit", typeof(int)); } emit .stobj(typeof(NameOrIndexParameter)) .end() ; } emit .newobj(typeof(MapIndex), typeof(NameOrIndexParameter[])) .stsfld(fieldBuilder) ; } return fieldBuilder; } /// <summary> /// Maps primary keys(s) to a scalar field. /// </summary> void ExecuteScalarDictionaryWithPK( Type keyType, NameOrIndexParameter scalarField, Type elementType) { CreateReturnTypeInstance(); InitObjectType(); Context.MethodBuilder.Emitter .ldarg_0 .end() ; GetSprocNameOrSqlQueryTest(); CallSetCommand(); LoadDestinationOrReturnValue(); Context.MethodBuilder.Emitter .ldloc(_locObjType) .LoadType(keyType) .ldstr(Context.CurrentMethod.Name) .ldNameOrIndex(scalarField) .LoadType(elementType) .callvirt(_baseType, "ExecuteScalarDictionary", _bindingFlags, typeof(DbManager), typeof(IDictionary), typeof(Type), typeof(Type), typeof(string), typeof(NameOrIndexParameter), typeof(Type)) ; } /// <summary> /// Maps a complex index to a scalar field. /// </summary> void ExecuteScalarDictionaryWithMapIndex( NameOrIndexParameter[] index, NameOrIndexParameter scalarField, Type elementType) { _objectType = elementType; CreateReturnTypeInstance(); InitObjectType(); GetSprocNameOrSqlQueryTest(); CallSetCommand(); LoadDestinationOrReturnValue(); Context.MethodBuilder.Emitter .ldsfld(GetIndexField(index)) .ldNameOrIndex(scalarField) .ldloc(_locObjType) .callvirt(typeof(DbManager), "ExecuteScalarDictionary", typeof(IDictionary), typeof(MapIndex), typeof(NameOrIndexParameter), typeof(Type)) .pop .end() ; } /// <summary> /// Maps any single field to any (other) single field. /// </summary> void ExecuteScalarDictionaryWithScalarKey( NameOrIndexParameter keyField, Type keyType, NameOrIndexParameter scalarField, Type elementType) { _objectType = elementType; CreateReturnTypeInstance(); InitObjectType(); GetSprocNameOrSqlQueryTest(); CallSetCommand(); LoadDestinationOrReturnValue(); Context.MethodBuilder.Emitter .ldNameOrIndex(keyField) .LoadType(keyType) .ldNameOrIndex(scalarField) .ldloc(_locObjType) .callvirt(typeof(DbManager), "ExecuteScalarDictionary", typeof(IDictionary), typeof(NameOrIndexParameter), typeof(Type), typeof(NameOrIndexParameter), typeof(Type)) .pop .end() ; } /// <summary> /// Maps primary keys(s) to an object of the specified type. /// </summary> void ExecuteDictionaryWithPK( Type keyType, Type elementType) { EmitHelper emit = Context.MethodBuilder.Emitter; _objectType = elementType; CreateReturnTypeInstance(); InitObjectType(); emit .ldarg_0 .end() ; GetSprocNameOrSqlQueryTest(); CallSetCommand(); LoadDestinationOrReturnValue(); if (IsGenericDestinationOrReturnValue()) { Type[] genericArgs = Context.ReturnValue.LocalType.GetGenericArguments(); Type[] types = new Type[] { typeof(DbManager), typeof(IDictionary<,>).MakeGenericType(genericArgs), typeof(Type), typeof(string), }; MethodInfo method = _baseType.GetMethod("ExecuteDictionary", _bindingFlags, GenericBinder.Generic, types, null); if (TypeHelper.IsSameOrParent(typeof(CompoundValue), genericArgs[0])) method = method.MakeGenericMethod(genericArgs[1]); else method = method.MakeGenericMethod(genericArgs); emit .ldloc(_locObjType) .ldstr(Context.CurrentMethod.Name) .callvirt(method) ; } else emit .ldloc(_locObjType) .LoadType(keyType) .ldstr(Context.CurrentMethod.Name) .callvirt(_baseType, "ExecuteDictionary", _bindingFlags, typeof(DbManager), typeof(IDictionary), typeof(Type), typeof(Type), typeof(string)) ; } /// <summary> /// Maps a complex index to an object of the specified type. /// </summary> void ExecuteDictionaryWithMapIndex( NameOrIndexParameter[] index, Type elementType) { _objectType = elementType; CreateReturnTypeInstance(); InitObjectType(); GetSprocNameOrSqlQueryTest(); CallSetCommand(); LoadDestinationOrReturnValue(); Context.MethodBuilder.Emitter .ldsfld(GetIndexField(index)) .ldloc(_locObjType) .ldnull .callvirt(typeof(DbManager), "ExecuteDictionary", typeof(IDictionary), typeof(MapIndex), typeof(Type), typeof(object[])) .pop .end() ; } /// <summary> /// Maps any single field to object type. /// </summary> void ExecuteDictionaryWithScalarKey( NameOrIndexParameter keyField, Type elementType) { EmitHelper emit = Context.MethodBuilder.Emitter; _objectType = elementType; CreateReturnTypeInstance(); InitObjectType(); GetSprocNameOrSqlQueryTest(); CallSetCommand(); LoadDestinationOrReturnValue(); if (IsGenericDestinationOrReturnValue()) { Type[] genericArgs = Context.ReturnValue.LocalType.GetGenericArguments(); Type[] types = new Type[] { typeof(IDictionary<,>).MakeGenericType(genericArgs), typeof(NameOrIndexParameter), typeof(Type), typeof(object[]), }; MethodInfo method = typeof(DbManager).GetMethod("ExecuteDictionary", _bindingFlags, GenericBinder.Generic, types, null) .MakeGenericMethod(genericArgs); emit .ldNameOrIndex(keyField) .ldloc(_locObjType) .ldnull .callvirt(method) .pop .end() ; } else { emit .ldNameOrIndex(keyField) .ldloc(_locObjType) .ldnull .callvirt(typeof(DbManager), "ExecuteDictionary", typeof(IDictionary), typeof(NameOrIndexParameter), typeof(Type), typeof(object[])) .pop .end() ; } } #endregion #region ExecuteEnumerable public void ExecuteEnumerable() { EmitHelper emit = Context.MethodBuilder.Emitter; Type returnType = Context.CurrentMethod.ReturnType; if (_objectType == null && returnType.IsGenericType) _objectType = returnType.GetGenericArguments()[0]; if (_objectType == null || _objectType == typeof(object)) ThrowTypeBuilderException(Resources.DataAccessorBuilder_BadListItemType); Type returnObjectType = returnType.IsGenericType ? returnType.GetGenericArguments()[0] : _objectType; InitObjectType(); Context.MethodBuilder.Emitter .ldarg_0 .end() ; GetSprocNameOrSqlQueryTest(); CallSetCommand(); Type[] genericArgs = new Type[] { returnObjectType }; Type[] types = new Type[] { typeof(DbManager), typeof(Type), typeof(bool), }; MethodInfo method = _baseType .GetMethod("ExecuteEnumerable", _bindingFlags, GenericBinder.Generic, types, null) .MakeGenericMethod(genericArgs); emit .LoadType(_objectType) .ldc_i4_1 .callvirt(method) .stloc(Context.ReturnValue) ; } #endregion #region ExecuteNonQuery public void ExecuteNonQuery() { if (_destination != null) throw new TypeBuilderException(Resources.DataAccessorBuilder_CantExecuteNonQueryToDestination); InitObjectType(); GetSprocNameOrSqlQueryTest(); CallSetCommand(); MethodInfo mi = typeof(DbManager).GetMethod("ExecuteNonQuery", Type.EmptyTypes); LocalBuilder locExec = Context.MethodBuilder.Emitter.DeclareLocal(mi.ReturnType); Context.MethodBuilder.Emitter .callvirt(mi) .stloc(locExec) ; if (Context.ReturnValue != null) { Context.MethodBuilder.Emitter .ldloc(locExec) .stloc(Context.ReturnValue) ; } } #endregion #region ExecuteScalar public void ExecuteScalar() { EmitHelper emit = Context.MethodBuilder.Emitter; Type returnType = Context.CurrentMethod.ReturnType; Type scalarType; if (_destination != null) { if (_destination.ParameterType.IsByRef) scalarType = _destination.ParameterType.GetElementType(); else throw new TypeBuilderException(Resources.DataAccessorBuilder_ScalarDestinationIsNotByRef); if (returnType != typeof(void) && !TypeHelper.IsSameOrParent(returnType, scalarType)) { // object Foo(out int num) is valid, // IConvertible Foo(ref int num) is also ok, // but string Bar(out DateTime dt) is not // throw new TypeBuilderException(string.Format( Resources.DataAccessorBuilder_IncompatibleDestinationType, returnType.FullName, Context.CurrentMethod.Name, scalarType.FullName)); } } else scalarType = returnType; if (_destination != null) emit .ldarg(_destination) ; emit .ldarg_0 .ldloc(_locManager) ; InitObjectType(); GetSprocNameOrSqlQueryTest(); CallSetCommand(); object[] attrs = Context.CurrentMethod.GetCustomAttributes(typeof(ScalarSourceAttribute), true); if (attrs.Length == 0) { emit .callvirtNoGenerics(typeof(DbManager), "ExecuteScalar") ; } else { ScalarSourceAttribute attr = (ScalarSourceAttribute)attrs[0]; emit .ldc_i4_((int)attr.ScalarType) .ldNameOrIndex(attr.NameOrIndex) .callvirtNoGenerics(typeof(DbManager), "ExecuteScalar", typeof(ScalarSourceType), typeof(NameOrIndexParameter)); } MethodInfo converter = GetConverterMethod(scalarType); if (converter == null) { emit .LoadType(scalarType) .ldnull .callvirt(_baseType, "ConvertChangeType", _bindingFlags, typeof(DbManager), typeof(object), typeof(Type), typeof(object)) .unboxIfValueType(scalarType) ; } else { emit .ldnull .callvirt(converter) ; } if (_destination != null) { emit .stind(scalarType) ; // The return value and a destination both are present // if (Context.ReturnValue != null) { emit .ldargEx(_destination, false) ; if (scalarType != returnType) emit .boxIfValueType(scalarType) .CastFromObject(returnType) ; emit.stloc(Context.ReturnValue) ; } } else emit .stloc(Context.ReturnValue) ; } #endregion #region ExecuteObject public void ExecuteObject() { InitObjectType(); GetSprocNameOrSqlQueryTest(); CallSetCommand(); EmitHelper emit = Context.MethodBuilder.Emitter; if (_destination != null) { emit .ldarg(_destination) .callvirt(typeof(DbManager), "ExecuteObject", typeof(Object)) ; } else { emit .ldloc(_locObjType) .callvirt(typeof(DbManager), "ExecuteObject", typeof(Type)) ; } if (null != Context.ReturnValue) { emit .castclass(_objectType) .stloc(Context.ReturnValue) ; } else { emit .pop .end() ; } } #endregion void Finally() { if (_createManager) { Context.MethodBuilder.Emitter .BeginFinallyBlock() .ldarg_0 .ldloc(_locManager) .callvirt(_baseType, "Dispose", _bindingFlags, typeof(DbManager)) .EndExceptionBlock() ; } } void CreateReturnTypeInstance() { if (null == Context.ReturnValue) return; if (null != _destination) { Context.MethodBuilder.Emitter .ldarg(_destination) .CastIfNecessary(Context.ReturnValue.LocalType, _destination.ParameterType) .stloc(Context.ReturnValue) ; } else { Type returnType = Context.CurrentMethod.ReturnType; if (returnType.IsInterface) { if (IsInterfaceOf(returnType, typeof(IList))) returnType = typeof(ArrayList); else if (IsInterfaceOf(returnType, typeof(IDictionary))) returnType = typeof(Hashtable); else if (returnType.GetGenericTypeDefinition() == typeof(IList<>)) returnType = typeof(List<>).MakeGenericType(returnType.GetGenericArguments()); else if (returnType.GetGenericTypeDefinition() == typeof(IDictionary<,>)) returnType = typeof(Dictionary<,>).MakeGenericType(returnType.GetGenericArguments()); } ConstructorInfo ci = TypeHelper.GetDefaultConstructor(returnType); if (ci == null) throw new TypeBuilderException(string.Format(Resources.DataAccessorBuilder_CantCreateTypeInstance, Context.CurrentMethod.ReturnType.FullName)); Context.MethodBuilder.Emitter .newobj(ci) .stloc(Context.ReturnValue) ; } } Type MethodReturnType { get { return _destination != null ? _destination.ParameterType : Context.CurrentMethod.ReturnType; } } void LoadDestinationOrReturnValue() { if (_destination != null) Context.MethodBuilder.Emitter.ldarg(_destination); else Context.MethodBuilder.Emitter.ldloc(Context.ReturnValue); } bool IsGenericDestinationOrReturnValue() { return _destination == null ? Context.ReturnValue.LocalType.IsGenericType : _destination.ParameterType.IsGenericType; } void InitObjectType() { Context.MethodBuilder.Emitter .LoadType(_objectType) .stloc(_locObjType) ; } static int _nameCounter; static int _uniqueQueryID; void GetSprocNameOrSqlQueryTest() { EmitHelper emit = Context.MethodBuilder.Emitter; if (_sqlQueryAttribute != null) { emit .ldloc(_locManager) ; if (_sqlQueryAttribute.ID != int.MinValue) { emit .ldarg_0 .ldloc(_locManager) .ldc_i4_(_sqlQueryAttribute.ID) .ldc_i4_(++_uniqueQueryID) ; } if (_sqlQueryAttribute.IsDynamic) { Type attrType = typeof(SqlQueryAttribute); FieldBuilder field = Context.CreatePrivateStaticField(attrType + "$" + ++_nameCounter, attrType); Label isNull = emit.DefineLabel(); emit .ldsfld(field) .brtrue_s(isNull) .ldarg_0 .call(typeof(MethodBase), "GetCurrentMethod") .castclass(typeof(MethodInfo)) .callvirt(_baseType, "GetSqlQueryAttribute", _bindingFlags, typeof(MethodInfo)) .stsfld(field) .MarkLabel(isNull) .ldsfld(field) .ldarg_0 .ldloc(_locManager) .callvirt(attrType, "GetSqlText", _bindingFlags, typeof(DataAccessor), typeof(DbManager)) ; } else { emit .ldstr(_sqlQueryAttribute.SqlText) ; } if (_sqlQueryAttribute.ID != int.MinValue) { emit .callvirt(_baseType, "PrepareSqlQuery", _bindingFlags, typeof(DbManager), typeof(int), typeof(int), typeof(string)) ; } } else { object[] attrs = Context.CurrentMethod.GetCustomAttributes(typeof(SprocNameAttribute), true); if (attrs.Length == 0) { attrs = Context.CurrentMethod.GetCustomAttributes(typeof(ActionNameAttribute), true); string actionName = attrs.Length == 0 ? Context.CurrentMethod.Name : ((ActionNameAttribute)attrs[0]).Name; // Call GetSpName. // emit .ldloc(_locManager) .ldarg_0 .ldloc(_locObjType) .ldstr(actionName) .callvirt(_baseType, "GetSpName", _bindingFlags, typeof(Type), typeof(string)) ; } else { emit .ldloc(_locManager) .ldstr(((SprocNameAttribute)attrs[0]).Name) ; } } // string.Format // if (_formatParamList.Count > 0) { emit .ldc_i4_(_formatParamList.Count) .newarr(typeof(object)) ; for (int i = 0; i < _formatParamList.Count; i++) { ParameterInfo pi = (ParameterInfo)_formatParamList[i]; emit .dup .ldc_i4_(i) .ldarg(pi) .boxIfValueType(pi.ParameterType) .stelem_ref .end() ; } emit .call(typeof(string), "Format", typeof(string), typeof(object[])) ; } } void CallSetCommand() { EmitHelper emit = Context.MethodBuilder.Emitter; // Get DiscoverParametersAttribute. // object[] attrs = Context.CurrentMethod.DeclaringType.GetCustomAttributes(typeof(DiscoverParametersAttribute), true); bool discoverParams = false; if (_sqlQueryAttribute == null) { discoverParams = attrs.Length == 0 ? false : ((DiscoverParametersAttribute)attrs[0]).Discover; attrs = Context.CurrentMethod.GetCustomAttributes(typeof(DiscoverParametersAttribute), true); if (attrs.Length != 0) discoverParams = ((DiscoverParametersAttribute)attrs[0]).Discover; } LocalBuilder locParams = discoverParams ? BuildParametersWithDiscoverParameters() : BuildParameters(); // Call SetSpCommand. // string methodName = _sqlQueryAttribute == null ? "SetSpCommand" : "SetCommand"; Type paramType = _sqlQueryAttribute == null ? typeof(object[]) : typeof(IDbDataParameter[]); emit .ldloc(locParams) .callvirt(typeof(DbManager), methodName, _bindingFlags, typeof(string), paramType) ; } LocalBuilder BuildParameters() { EmitHelper emit = Context.MethodBuilder.Emitter; LocalBuilder retParams = emit .DeclareLocal(typeof(IDbDataParameter[])); LocalBuilder locParams = _refParamList.Count > 0 ? BuildRefParameters() : BuildSimpleParameters(); emit .ldarg_0 .ldloc(_locManager) .ldloc(locParams) .callvirt(_baseType, "PrepareParameters", _bindingFlags, typeof(DbManager), typeof(object[])) .stloc(retParams) ; return retParams; } LocalBuilder BuildSimpleParameters() { EmitHelper emit = Context.MethodBuilder.Emitter; // Parameters. // LocalBuilder locParams = emit.DeclareLocal( _sqlQueryAttribute == null ? typeof(object[]) : typeof(IDbDataParameter[])); emit .ldc_i4_(_paramList.Count) .newarr(_sqlQueryAttribute == null ? typeof(object) : typeof(IDbDataParameter)) ; for (int i = 0; i < _paramList.Count; i++) { ParameterInfo pi = (ParameterInfo)_paramList[i]; emit .dup .ldc_i4_(i) ; BuildParameter(pi); emit .stelem_ref .end() ; } emit.stloc(locParams); return locParams; } FieldBuilder CreateStringArrayField(object[] attrs) { if (attrs.Length == 0) return null; List<string> list = new List<string>(); foreach (Direction attr in attrs) if (attr.Members != null) list.AddRange(attr.Members); if (list.Count == 0) return null; list.Sort(string.CompareOrdinal); string[] strings = list.ToArray(); // There a no limit for a field name length, but Visual Studio Debugger // may crash on fields with name longer then 256 symbols. // string key = "_string_array$" + string.Join("%", strings); FieldBuilder fieldBuilder = Context.GetField(key); if (null == fieldBuilder) { fieldBuilder = Context.CreatePrivateStaticField(key, typeof(string[])); EmitHelper emit = Context.TypeBuilder.TypeInitializer.Emitter; emit .ldc_i4_(strings.Length) .newarr(typeof(string)) ; for (int i = 0; i < strings.Length; i++) { emit .dup .ldc_i4_(i) .ldstr(strings[i]) .stelem_ref .end() ; } emit .stsfld(fieldBuilder) ; } return fieldBuilder; } FieldBuilder CreateNullValueField(Type type, string value) { string key = "_null_value$" + type.FullName + "%" + value; FieldBuilder fieldBuilder = Context.GetField(key); if (null == fieldBuilder) { fieldBuilder = Context.CreatePrivateStaticField(key, type); EmitHelper emit = Context.TypeBuilder.TypeInitializer.Emitter; emit .LoadType(type) .call(typeof(TypeDescriptor), "GetConverter", typeof(Type)) .ldstr(value) .callvirt(typeof(TypeConverter), "ConvertFromInvariantString", typeof(string)) .unbox_any(type) .stsfld(fieldBuilder) ; } return fieldBuilder; } LocalBuilder BuildRefParameters() { EmitHelper emit = Context.MethodBuilder.Emitter; // Parameters. // LocalBuilder locParams = emit.DeclareLocal(typeof(object[])); emit .ldc_i4_(_parameters.Length) .newarr(typeof(object)) ; for (int i = 0; i < _parameters.Length; i++) { ParameterInfo pi = _parameters[i]; emit .dup .ldc_i4_(i) ; if (_paramList.Contains(pi)) { BuildParameter(pi); } else if (_refParamList.Contains(pi)) { var mapOutputParameters = false; string returnValueMember = null; FieldBuilder fieldBuilder; var type = pi.ParameterType == typeof(DataRow) || pi.ParameterType.IsSubclassOf(typeof(DataRow)) ? typeof(DataRow) : typeof(object); emit .ldarg_0 .ldloc(_locManager) .ldarg(pi) ; fieldBuilder = CreateStringArrayField(pi.GetCustomAttributes(typeof(Direction.OutputAttribute), true)); if (fieldBuilder != null) { emit.ldsfld(fieldBuilder); mapOutputParameters = true; } else emit.ldnull.end(); fieldBuilder = CreateStringArrayField(pi.GetCustomAttributes(typeof(Direction.InputOutputAttribute), true)); if (fieldBuilder != null) { emit.ldsfld(fieldBuilder); mapOutputParameters = true; } else emit.ldnull.end(); fieldBuilder = CreateStringArrayField(pi.GetCustomAttributes(typeof(Direction.IgnoreAttribute), true)); if (fieldBuilder != null) emit.ldsfld(fieldBuilder); else emit.ldnull.end(); emit .ldnull .callvirt(_baseType, "CreateParameters", _bindingFlags, typeof(DbManager), type, typeof(string[]), typeof(string[]), typeof(string[]), typeof(IDbDataParameter[])) ; object[] attrs = pi.GetCustomAttributes(typeof(Direction.ReturnValueAttribute), true); if (attrs.Length != 0) returnValueMember = ((Direction.ReturnValueAttribute)attrs[0]).Member; if (null != returnValueMember || mapOutputParameters) _mapOutputParameters.Add(new MapOutputParametersValue(returnValueMember, pi)); } else { emit .ldnull .end() ; } emit .stelem_ref .end() ; } emit.stloc(locParams); return locParams; } void LoadParameterOrNull(ParameterInfo pi, Type type) { EmitHelper emit = Context.MethodBuilder.Emitter; object[] attrs = pi.GetCustomAttributes(typeof(ParamNullValueAttribute), true); object nullValue = attrs.Length == 0 ? null : ((ParamNullValueAttribute)attrs[0]).Value; Label labelNull = emit.DefineLabel(); Label labelEndIf = emit.DefineLabel(); if (pi.Attributes == ParameterAttributes.Out) { emit .ldnull .end() ; return; } if (nullValue != null) { Type nullValueType = type; bool isNullable = TypeHelper.IsNullable(type); if (type.IsEnum) { nullValueType = Enum.GetUnderlyingType(type); nullValue = System.Convert.ChangeType(nullValue, nullValueType); } else if (isNullable) { nullValueType = type.GetGenericArguments()[0]; emit .ldarga(pi) .call(type, "get_HasValue") .brfalse(labelNull) ; } if (nullValueType == nullValue.GetType() && emit.LoadWellKnownValue(nullValue)) { if (nullValueType == typeof(string)) emit .ldargEx(pi, false) .call(nullValueType, "Equals", nullValueType) .brtrue(labelNull) ; else if (isNullable) emit .ldarga(pi) .call(type, "get_Value") .beq(labelNull) ; else emit .ldargEx(pi, false) .beq(labelNull) ; } else { string nullString = TypeDescriptor.GetConverter(nullValue).ConvertToInvariantString(nullValue); FieldBuilder staticField = CreateNullValueField(nullValueType, nullString); MethodInfo miEquals = new TypeHelper(nullValueType).GetPublicMethod("Equals", nullValueType); if (miEquals == null) { // Is it possible? // throw new TypeBuilderException(string.Format( Resources.DataAccessorBuilder_EqualsMethodIsNotPublic, type.FullName)); } if (isNullable) emit .ldsflda(staticField) .ldarga(pi) .call(pi.ParameterType, "get_Value") ; else emit .ldsflda(staticField) .ldarg(pi) ; if (miEquals.GetParameters()[0].ParameterType.IsClass) emit .boxIfValueType(nullValueType) ; emit .call(miEquals) .brtrue(labelNull) ; } } if (type.IsEnum) emit .ldloc(_locManager) .callvirt(typeof(DbManager).GetProperty("MappingSchema").GetGetMethod()) ; emit .ldargEx(pi, true) ; if (type.IsEnum) emit .ldc_i4_1 .callvirt(typeof(MappingSchema), "MapEnumToValue", typeof(object), typeof(bool)) ; if (nullValue != null) { emit .br(labelEndIf) .MarkLabel(labelNull) .ldnull .MarkLabel(labelEndIf) ; } } void BuildParameter(ParameterInfo pi) { EmitHelper emit = Context.MethodBuilder.Emitter; Type type = pi.ParameterType; object[] attrs = pi.GetCustomAttributes(typeof(ParamNameAttribute), true); string paramName = attrs.Length == 0 ? pi.Name : ((ParamNameAttribute)attrs[0]).Name; ParameterDirection direction = !type.IsByRef ? ParameterDirection.Input : pi.IsOut ? ParameterDirection.Output : ParameterDirection.InputOutput; emit .ldloc(_locManager) .ldc_i4_((int)direction) ; if (paramName[0] != '@') { string methodName = _sqlQueryAttribute == null ? "GetSpParameterName" : "GetQueryParameterName"; emit .ldarg_0 .ldloc(_locManager) .ldstr(paramName) .callvirt(_baseType, methodName, _bindingFlags, typeof(DbManager), typeof(string)) ; } else emit.ldstr(paramName); if (type.IsByRef) { if (_outputParameters == null) _outputParameters = new ArrayList(); _outputParameters.Add(pi); type = type.GetElementType(); } LoadParameterOrNull(pi, type); // Special case for user-defined types. // attrs = pi.GetCustomAttributes(typeof(ParamTypeNameAttribute), true); if (attrs.Length > 0) { emit .ldstr(((ParamTypeNameAttribute)attrs[0]).TypeName) .callvirt(typeof(DbManager), "Parameter", typeof(ParameterDirection), typeof(string), typeof(object), typeof(string)) ; } else { emit .callvirt(typeof(DbManager), "Parameter", typeof(ParameterDirection), typeof(string), typeof(object)) ; } // Check if parameter type/size is specified. // attrs = pi.GetCustomAttributes(typeof(ParamDbTypeAttribute), true); if (attrs.Length > 0) { emit .dup .ldc_i4_((int)((ParamDbTypeAttribute)attrs[0]).DbType) .callvirt(typeof(IDataParameter), "set_DbType", typeof(DbType)) ; } attrs = pi.GetCustomAttributes(typeof(ParamSizeAttribute), true); if (attrs.Length > 0) { emit .dup .ldc_i4_(((ParamSizeAttribute)attrs[0]).Size) .callvirt(typeof(IDbDataParameter), "set_Size", typeof(int)) ; } } LocalBuilder BuildParametersWithDiscoverParameters() { EmitHelper emit = Context.MethodBuilder.Emitter; LocalBuilder locParams = emit.DeclareLocal(typeof(object[])); emit .ldc_i4_(_paramList.Count) .newarr(typeof(object)) ; for (int i = 0; i < _paramList.Count; i++) { ParameterInfo pi = (ParameterInfo)_paramList[i]; emit .dup .ldc_i4_(i) ; LoadParameterOrNull(pi, pi.ParameterType); emit .stelem_ref .end() ; } emit.stloc(locParams); return locParams; } void StoreParameterValue(LocalBuilder param, ParameterInfo pi, Type type) { EmitHelper emit = Context.MethodBuilder.Emitter; Label labelNull = emit.DefineLabel(); Label labelEndIf = emit.DefineLabel(); object[] attrs = pi.GetCustomAttributes(typeof(ParamNullValueAttribute), true); object nullValue = attrs.Length == 0 ? null : ((ParamNullValueAttribute)attrs[0]).Value; if (nullValue != null) { emit .ldarg_0 .ldloc(_locManager) .ldloc(param) .callvirt(typeof(IDataParameter).GetProperty("Value").GetGetMethod()) .ldloc(param) .callvirt(_baseType, "IsNull", _bindingFlags, typeof(DbManager), typeof(object), typeof(object)) .brtrue(labelNull) ; } if (type.IsEnum) { emit .ldloc(_locManager) .callvirt(typeof(DbManager).GetProperty("MappingSchema").GetGetMethod()) .ldloc(param) .callvirt(typeof(IDataParameter).GetProperty("Value").GetGetMethod()) .LoadType(type) .callvirt(typeof(MappingSchema), "MapValueToEnum", typeof(object), typeof(Type)) .CastFromObject(type) ; } #if FW4 else if (pi.IsRefCursor()) { // Make sure the parameter is a List if (!type.GetInterfaces().Contains(typeof(IList))) { throw new Exception("The argument '" + pi.Name + "' must be of type 'IList'"); } //Get the generic type of the list Type genericType = type.GetGenericArguments().First(); // Get the data reader to the ref cursor var dataReader = emit.DeclareLocal(typeof(IDataReader)); emit .ldloc(_locManager) .callvirt(typeof(DbManager).GetProperty("DataProvider").GetGetMethod()) .ldloc(param) .callvirt(typeof(IDataParameter).GetProperty("Value").GetGetMethod()) .callvirt(typeof(DataProviderBase), "GetRefCursorDataReader", typeof(object)) .CastFromObject(typeof(IDataReader)) .stloc(dataReader) ; // Create the generic methos info to invoke var mapDataReaderToListMethodInfo = typeof (MappingSchema).GetMethod("MapDataReaderToList", new[] { typeof (IDataReader), typeof (object[]) }) .MakeGenericMethod(genericType); // Run MapDataReaderToList emit .ldloc(_locManager) .callvirt(typeof(DbManager).GetProperty("MappingSchema").GetGetMethod()) .ldloc(dataReader) .ldnull .callvirt(mapDataReaderToListMethodInfo) ; } #endif else { emit .ldarg_0 .ldloc(_locManager) .ldloc(param) .callvirt(typeof(IDataParameter).GetProperty("Value").GetGetMethod()) ; MethodInfo converter = GetConverterMethod(type); if (converter == null) { emit .LoadType(type) .ldloc(param) .callvirt(_baseType, "ConvertChangeType", _bindingFlags, typeof(DbManager), typeof(object), typeof(Type), typeof(object)) .unboxIfValueType(type) ; } else { emit .ldloc(param) .callvirt(converter) ; } } if (nullValue != null) { emit .br(labelEndIf) .MarkLabel(labelNull); if (nullValue.GetType() != type || !emit.LoadWellKnownValue(nullValue)) { string nullString = TypeDescriptor.GetConverter(type).ConvertToInvariantString(nullValue); FieldBuilder staticField = CreateNullValueField(type, nullString); emit .ldsfld(staticField) ; } emit .MarkLabel(labelEndIf) ; } emit.stind(type); } void GetOutRefParameters() { EmitHelper emit = Context.MethodBuilder.Emitter; if (_outputParameters != null) { LocalBuilder param = emit.DeclareLocal(typeof(IDataParameter)); foreach (ParameterInfo pi in _outputParameters) { Type type = pi.ParameterType.GetElementType(); emit .ldarg(pi) ; // Get parameter. // object[] attrs = pi.GetCustomAttributes(typeof(ParamNameAttribute), true); string paramName = attrs.Length == 0 ? pi.Name : ((ParamNameAttribute)attrs[0]).Name; emit .ldarg_0 .ldloc(_locManager) ; if (paramName[0] != '@') { string methodName = _sqlQueryAttribute == null ? "GetSpParameterName" : "GetQueryParameterName"; emit .ldarg_0 .ldloc(_locManager) .ldstr(paramName) .callvirt(_baseType, methodName, _bindingFlags, typeof(DbManager), typeof(string)) ; } else emit.ldstr(paramName); emit .callvirt(_baseType, "GetParameter", _bindingFlags, typeof(DbManager), typeof(string)) .stloc(param) ; StoreParameterValue(param, pi, type); } } foreach (MapOutputParametersValue v in _mapOutputParameters) { emit .ldloc(_locManager) .ldstrEx(v.ReturnValueMember) .ldarg(v.ParameterInfo) .callvirt(typeof(DbManager), "MapOutputParameters", typeof(string), typeof(object)); } } static bool IsInterfaceOf(Type type, Type interfaceType) { Type[] types = type.GetInterfaces(); foreach (Type t in types) if (t == interfaceType) return true; return type == interfaceType; } private MethodInfo GetConverterMethod(Type type) { if (type.IsEnum) type = Enum.GetUnderlyingType(type); Type[] types = new Type[] { typeof(DbManager), typeof(object), typeof(object) }; return _baseType.GetMethod("ConvertTo" + type.Name, _bindingFlags, null, types, null); } } }