private void CreateProperty(TypeBuilderHelper typeBuilderHelper) { var dbObjectContainerField = typeBuilderHelper.DefineField("dbObjectContainer", typeof(DbObjectContainer), FieldAttributes.Private); var objectContainerProperty = typeBuilderHelper.TypeBuilder.DefineProperty("DbObjectContainer", PropertyAttributes.HasDefault, typeof(DbObjectContainer), new[] { typeof(DbObjectContainer) }); var attributes = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig; var objectContainerGetMethod = typeBuilderHelper.DefineMethod("get_DbObjectContainer", attributes, typeof(DbObjectContainer), Type.EmptyTypes); var objectContainerGetMethodEmit = objectContainerGetMethod.Emitter; objectContainerGetMethodEmit .ldarg_0 .ldfld(dbObjectContainerField) .ret(); var objectContainerSetMethod = typeBuilderHelper.DefineMethod("set_DbObjectContainer", attributes, null, typeof(DbObjectContainer)); var objectContainerSetMethodEmit = objectContainerSetMethod.Emitter; objectContainerSetMethodEmit .ldarg_0 .ldarg_1 .stfld(dbObjectContainerField) .ret(); objectContainerProperty.SetGetMethod(objectContainerGetMethod); objectContainerProperty.SetSetMethod(objectContainerSetMethod); }
public static void UpdateType(string typeName, TypeBuilderHelper typeBuilderHelper, FieldInfo[] fieldInfos) { //Serialize var serializerEmit = typeBuilderHelper.DefineMethod(typeof(ISerializable).GetMethod("Serialize", new Type[] { typeof(BinaryWriter), typeof(IDictionary <object, int>), typeof(int) })).Emitter; var deserializeEmit = typeBuilderHelper.DefineMethod(typeof(ISerializable).GetMethod("Deserialize", new Type[] { typeof(BinaryReader), typeof(IDictionary <int, object>) })).Emitter; //Write type name so we can construct it again serializerEmit .ldarg_1 .ldstr(typeName) .call(typeof(BinaryWriter).GetMethod("Write", new[] { typeof(string) })) //Add current object to the object graph .ldarg_2 .ldarg_0 .ldarg_3 .call(typeof(IDictionary <object, int>).GetMethod("Add", new[] { typeof(object), typeof(int) })) .ldarg_3 .ldc_i4_1 .add .starg(3); //Serialize/Deserialize properties foreach (var fieldInfo in fieldInfos) { var fieldType = fieldInfo.FieldType; if (fieldType.IsPrimitive || fieldType == typeof(string) || fieldType == typeof(DateTime) || fieldType == typeof(decimal)) { primitiveSerializeEmitter.Emit(fieldInfo, ref serializerEmit, ref deserializeEmit); } else if (fieldType.IsArray) { arraySerializeEmitter.Emit(fieldInfo, ref serializerEmit, ref deserializeEmit); } else if (fieldType.IsGenericType && (fieldType.GetGenericTypeDefinition() == typeof(IDictionary <,>) || fieldType.GetGenericTypeDefinition() == typeof(Dictionary <,>))) { dictGenericEmitter.Emit(fieldInfo, ref serializerEmit, ref deserializeEmit); } else if (fieldType.IsGenericType && (fieldType.GetGenericTypeDefinition() == typeof(IList <>) || fieldType.GetGenericTypeDefinition() == typeof(List <>))) { iListGenericEmitter.Emit(fieldInfo, ref serializerEmit, ref deserializeEmit); } else if (fieldType.IsClass) { objectGenericEmitter.Emit(fieldInfo, ref serializerEmit, ref deserializeEmit); } } serializerEmit.ret(); deserializeEmit.ret(); }
private void BuildTypedSetterForNullable( MemberInfo mi, TypeBuilderHelper nestedType, Type memberType) { Type methodType = mi.DeclaringType; MethodInfo setMethod = null; if (mi is PropertyInfo) { setMethod = ((PropertyInfo)mi).GetSetMethod(); if (setMethod == null) { if (_type != _originalType) { setMethod = _type.GetMethod("set_" + mi.Name); methodType = _type; } if (setMethod == null || !IsMethodAccessible(setMethod)) { return; } } } Type setterType = (memberType.IsEnum ? Enum.GetUnderlyingType(memberType) : memberType); MethodInfo methodInfo = _memberAccessor.GetMethod("Set" + setterType.Name, typeof(object), setterType); if (methodInfo == null) { return; } MethodBuilderHelper method = nestedType.DefineMethod(methodInfo); EmitHelper emit = method.Emitter; emit .ldarg_1 .castType(methodType) .ldarg_2 .newobj(typeof(Nullable <>).MakeGenericType(memberType), memberType) .end(); if (mi is FieldInfo) { emit.stfld((FieldInfo)mi); } else { emit.callvirt(setMethod); } emit .ret() ; }
private void BuildTypedSetter( MemberInfo mi, TypeBuilderHelper nestedType, Type memberType, string typedPropertyName) { Type methodType = mi.DeclaringType; MethodInfo setMethod = null; if (mi is PropertyInfo) { setMethod = ((PropertyInfo)mi).GetSetMethod(); if (setMethod == null) { if (_type != _originalType) { setMethod = _type.GetMethod("set_" + mi.Name); methodType = _type; } if (setMethod == null || !IsMethodAccessible(setMethod)) { return; } } } MethodInfo methodInfo = _memberAccessor.GetMethod("Set" + typedPropertyName, typeof(object), memberType); if (methodInfo == null) { return; } MethodBuilderHelper method = nestedType.DefineMethod(methodInfo); EmitHelper emit = method.Emitter; emit .ldarg_1 .castType(methodType) .ldarg_2 .end(); if (mi is FieldInfo) { emit.stfld((FieldInfo)mi); } else { emit.callvirt(setMethod); } emit .ret() ; }
private void BuildTypedGetter( MemberInfo mi, TypeBuilderHelper nestedType, string typedPropertyName) { var methodType = mi.DeclaringType; var getMethod = null as MethodInfo; if (mi is PropertyInfo) { getMethod = ((PropertyInfo)mi).GetGetMethod(); if (getMethod == null) { if (_type != _originalType) { getMethod = _type.GetMethod("get_" + mi.Name); methodType = _type; } if (getMethod == null || !IsMethodAccessible(getMethod)) { return; } } } var methodInfo = _memberAccessor.GetMethod("Get" + typedPropertyName, typeof(object)); if (methodInfo == null) { return; } var method = nestedType.DefineMethod(methodInfo); var emit = method.Emitter; emit .ldarg_1 .castType(methodType) .end(); if (mi is FieldInfo) { emit.ldfld((FieldInfo)mi); } else { emit.callvirt(getMethod); } emit .ret() ; }
private void BuildTypedGetterForNullable( MemberInfo mi, TypeBuilderHelper nestedType, Type memberType) { var methodType = mi.DeclaringType; var getMethod = null as MethodInfo; if (mi is PropertyInfo) { getMethod = ((PropertyInfo)mi).GetGetMethod(); if (getMethod == null) { if (_type != _originalType) { getMethod = _type.GetMethod("get_" + mi.Name); methodType = _type; } if (getMethod == null || !IsMethodAccessible(getMethod)) { return; } } } var setterType = (memberType.IsEnum ? Enum.GetUnderlyingType(memberType) : memberType); var methodInfo = _memberAccessor.GetMethod("Get" + setterType.Name, typeof(object)); if (methodInfo == null) { return; } var method = nestedType.DefineMethod(methodInfo); var nullableType = typeof(Nullable <>).MakeGenericType(memberType); var emit = method.Emitter; emit .ldarg_1 .castType(methodType) .end(); if (mi is FieldInfo) { emit.ldflda((FieldInfo)mi); } else { var locNullable = emit.DeclareLocal(nullableType); emit .callvirt(getMethod) .stloc(locNullable) .ldloca(locNullable) ; } emit .call(nullableType, "get_Value") .ret() ; }
private void BuildCloneValueMethod( MemberInfo mi, TypeBuilderHelper nestedType, Type memberType ) { var methodType = mi.DeclaringType; var getMethod = null as MethodInfo; var setMethod = null as MethodInfo; if (mi is PropertyInfo) { getMethod = ((PropertyInfo)mi).GetGetMethod(); if (getMethod == null) { if (_type != _originalType) { getMethod = _type.GetMethod("get_" + mi.Name); methodType = _type; } if (getMethod == null || !IsMethodAccessible(getMethod)) { return; } } setMethod = ((PropertyInfo)mi).GetSetMethod(); if (setMethod == null) { if (_type != _originalType) { setMethod = _type.GetMethod("set_" + mi.Name); methodType = _type; } if (setMethod == null || !IsMethodAccessible(setMethod)) { return; } } } var method = nestedType.DefineMethod(_memberAccessor.GetMethod("CloneValue", typeof(object), typeof(object))); var emit = method.Emitter; emit .ldarg_2 .castType(methodType) .ldarg_1 .castType(methodType) .end(); if (mi is FieldInfo) { emit.ldfld((FieldInfo)mi); } else { emit.callvirt(getMethod); } if (typeof(string) != memberType && TypeHelper.IsSameOrParent(typeof(ICloneable), memberType)) { if (memberType.IsValueType) { emit .box(memberType) .callvirt(typeof(ICloneable), "Clone") .unbox_any(memberType) ; } else { var valueIsNull = emit.DefineLabel(); emit .dup .brfalse_s(valueIsNull) .callvirt(typeof(ICloneable), "Clone") .castclass(memberType) .MarkLabel(valueIsNull) ; } } if (mi is FieldInfo) { emit.stfld((FieldInfo)mi); } else { emit.callvirt(setMethod); } emit .ret() ; }
private void BuildGetter(MemberInfo mi, TypeBuilderHelper nestedType) { Type methodType = mi.DeclaringType; MethodInfo getMethod = null; if (mi is PropertyInfo) { getMethod = ((PropertyInfo)mi).GetGetMethod(); if (getMethod == null) { if (_type != _originalType) { getMethod = _type.GetMethod("get_" + mi.Name); methodType = _type; } if (getMethod == null || !IsMethodAccessible(getMethod)) { return; } } } MethodBuilderHelper method = nestedType.DefineMethod( _memberAccessor.GetMethod("GetValue", typeof(object))); EmitHelper emit = method.Emitter; emit .ldarg_1 .castType(methodType) .end(); if (mi is FieldInfo) { FieldInfo fi = (FieldInfo)mi; emit .ldfld(fi) .boxIfValueType(fi.FieldType) ; } else { PropertyInfo pi = (PropertyInfo)mi; emit .callvirt(getMethod) .boxIfValueType(pi.PropertyType) ; } emit .ret() ; nestedType.DefineMethod(_memberAccessor.GetProperty("HasGetter").GetGetMethod()).Emitter .ldc_i4_1 .ret() ; }
private void BuildTypedGetterForNullable( MemberInfo mi, TypeBuilderHelper nestedType, Type memberType) { var methodType = mi.DeclaringType; var getMethod = null as MethodInfo; if (mi is PropertyInfo) { getMethod = ((PropertyInfo)mi).GetGetMethod(); if (getMethod == null) { if (_type != _originalType) { getMethod = _type.GetMethod("get_" + mi.Name); methodType = _type; } if (getMethod == null || !IsMethodAccessible(getMethod)) return; } } var setterType = (memberType.IsEnum ? Enum.GetUnderlyingType(memberType) : memberType); var methodInfo = _memberAccessor.GetMethod("Get" + setterType.Name, typeof(object)); if (methodInfo == null) return; var method = nestedType.DefineMethod(methodInfo); var nullableType = typeof(Nullable<>).MakeGenericType(memberType); var emit = method.Emitter; emit .ldarg_1 .castType (methodType) .end(); if (mi is FieldInfo) { emit.ldflda ((FieldInfo)mi); } else { var locNullable = emit.DeclareLocal(nullableType); emit .callvirt (getMethod) .stloc (locNullable) .ldloca (locNullable) ; } emit .call(nullableType, "get_Value") .ret() ; }
private void BuildTypedGetter( MemberInfo mi, TypeBuilderHelper nestedType, string typedPropertyName) { var methodType = mi.DeclaringType; var getMethod = null as MethodInfo; if (mi is PropertyInfo) { getMethod = ((PropertyInfo)mi).GetGetMethod(); if (getMethod == null) { if (_type != _originalType) { getMethod = _type.GetMethod("get_" + mi.Name); methodType = _type; } if (getMethod == null || !IsMethodAccessible(getMethod)) return; } } var methodInfo = _memberAccessor.GetMethod("Get" + typedPropertyName, typeof(object)); if (methodInfo == null) return; var method = nestedType.DefineMethod(methodInfo); var emit = method.Emitter; emit .ldarg_1 .castType (methodType) .end(); if (mi is FieldInfo) emit.ldfld ((FieldInfo)mi); else emit.callvirt(getMethod); emit .ret() ; }
private void BuildSetter(MemberInfo mi, TypeBuilderHelper nestedType) { var methodType = mi.DeclaringType; var setMethod = null as MethodInfo; if (mi is PropertyInfo) { setMethod = ((PropertyInfo)mi).GetSetMethod(); if (setMethod == null) { if (_type != _originalType) { setMethod = _type.GetMethod("set_" + mi.Name); methodType = _type; } if (setMethod == null || !IsMethodAccessible(setMethod)) return; } } //else if (((FieldInfo)mi).IsLiteral) // return; var method = nestedType.DefineMethod(_memberAccessor.GetMethod("SetValue", typeof(object), typeof(object))); var emit = method.Emitter; emit .ldarg_1 .castType (methodType) .ldarg_2 .end(); if (mi is FieldInfo) { var fi = (FieldInfo)mi; emit .CastFromObject (fi.FieldType) .stfld (fi) ; } else { var pi = (PropertyInfo)mi; emit .CastFromObject (pi.PropertyType) .callvirt (setMethod) ; } emit .ret() ; nestedType.DefineMethod(_memberAccessor.GetProperty("HasSetter").GetGetMethod()).Emitter .ldc_i4_1 .ret() ; }
void BuildCreateInstanceMethods() { var isValueType = _type.IsValueType; var baseDefCtor = isValueType? null: _type.GetPublicDefaultConstructor(); var baseInitCtor = _type.GetPublicConstructor(typeof(InitContext)); if (baseDefCtor == null && baseInitCtor == null && !isValueType) { return; } // CreateInstance. // var method = _typeBuilder.DefineMethod(_accessorType.GetMethod(false, "CreateInstance", Type.EmptyTypes)); if (baseDefCtor != null) { method.Emitter .newobj(baseDefCtor) .ret() ; } else if (isValueType) { var locObj = method.Emitter.DeclareLocal(_type); method.Emitter .ldloca(locObj) .initobj(_type) .ldloc(locObj) .box(_type) .ret() ; } else { method.Emitter .ldnull .newobj(baseInitCtor) .ret() ; } // CreateInstance(IniContext). // method = _typeBuilder.DefineMethod( _accessorType.GetMethod(false, "CreateInstance", typeof(InitContext))); if (baseInitCtor != null) { method.Emitter .ldarg_1 .newobj(baseInitCtor) .ret() ; } else if (isValueType) { var locObj = method.Emitter.DeclareLocal(_type); method.Emitter .ldloca(locObj) .initobj(_type) .ldloc(locObj) .box(_type) .ret() ; } else { method.Emitter .newobj(baseDefCtor) .ret() ; } }
private bool BuildMembers(Type interfaceType) { FieldInfo objectsField = typeof(DuckType).GetField("_objects", BindingFlags.NonPublic | BindingFlags.Instance); BindingFlags flags = BindingFlags.Public | BindingFlags.Instance | (DuckTyping.AllowStaticMembers? BindingFlags.Static | BindingFlags.FlattenHierarchy: 0); foreach (MethodInfo interfaceMethod in interfaceType.GetMethods(BindingFlags.Public | BindingFlags.Instance)) { MethodInfo targetMethod = null; int typeIndex = 0; for (; typeIndex < _objectTypes.Length; typeIndex++) { if (_objectTypes[typeIndex] == null) { continue; } foreach (MethodInfo mi in _objectTypes[typeIndex].GetMethods(flags)) { if (CompareMethodSignature(interfaceMethod, mi)) { targetMethod = mi; break; } } if (targetMethod == null) { foreach (Type intf in _objectTypes[typeIndex].GetInterfaces()) { if (intf.IsPublic || intf.IsNestedPublic) { foreach (MethodInfo mi in intf.GetMethods(flags)) { if (CompareMethodSignature(interfaceMethod, mi)) { targetMethod = mi; break; } } if (targetMethod != null) { break; } } } } if (targetMethod != null) { break; } } ParameterInfo[] ips = interfaceMethod.GetParameters(); MethodBuilderHelper builder = _typeBuilder.DefineMethod(interfaceMethod); EmitHelper emit = builder.Emitter; if (targetMethod != null) { Type targetType = targetMethod.DeclaringType; if (!targetMethod.IsStatic) { emit .ldarg_0 .ldfld(objectsField) .ldc_i4(typeIndex) .ldelem_ref .end() ; if (targetType.IsValueType) { // For value types we have to use stack. // LocalBuilder obj = emit.DeclareLocal(targetType); emit .unbox_any(targetType) .stloc(obj) .ldloca(obj) ; } else { emit .castclass(targetType) ; } } foreach (ParameterInfo p in ips) { emit.ldarg(p); } if (targetMethod.IsStatic || targetMethod.IsFinal || targetMethod.DeclaringType.IsSealed) { emit .call(targetMethod) .ret(); } else { emit .callvirt(targetMethod) .ret(); } } else { // Method or property was not found. // Insert an empty stub or stub that throws the NotImplementedException. // MustImplementAttribute attr = (MustImplementAttribute) Attribute.GetCustomAttribute(interfaceMethod, typeof(MustImplementAttribute)); if (attr == null) { attr = (MustImplementAttribute)Attribute.GetCustomAttribute( interfaceMethod.DeclaringType, typeof(MustImplementAttribute)); if (attr == null) { attr = _defaultAttribute; } } // When the member is marked as 'Required' throw a build-time exception. // if (attr.Implement) { if (attr.ThrowException) { throw new TypeBuilderException(string.Format( Resources.TypeBuilder_PublicMethodMustBeImplemented, _objectTypes.Length > 0 && _objectTypes[0] != null ? _objectTypes[0].FullName : "???", interfaceMethod)); } else { // Implement == true, but ThrowException == false. // In this case the null pointer will be returned. // This mimics the 'as' operator behaviour. // return(false); } } if (attr.ThrowException) { string message = attr.ExceptionMessage; if (message == null) { message = string.Format(Resources.TypeBuilder_PublicMethodNotImplemented, _objectTypes.Length > 0 && _objectTypes[0] != null ? _objectTypes[0].FullName : "???", interfaceMethod); } emit .ldstr(message) .newobj(typeof(NotImplementedException), typeof(string)) .@throw .end(); } else { // Emit a 'do nothing' stub. // LocalBuilder returnValue = null; if (interfaceMethod.ReturnType != typeof(void)) { returnValue = emit.DeclareLocal(interfaceMethod.ReturnType); emit.Init(returnValue); } // Initialize out parameters. // ParameterInfo[] parameters = ips; if (parameters != null) { emit.InitOutParameters(parameters); } if (returnValue != null) { emit.ldloc(returnValue); } emit.ret(); } } } return(true); }
private void CreateUpdateFunction(Type type, TypeBuilderHelper typeBuilderHelper) { var classMetadata = ClassMetaDataManager.Instace.GetClassMetaData(type); var properties = classMetadata.Properties; var mappingTable = classMetadata.MappingTable; var methodEmit = typeBuilderHelper.DefineMethod(typeof(IDbFunctionHelper).GetMethod("Update")).Emitter; var resultLocal = methodEmit.DeclareLocal(typeof(int)); var commandLocal = methodEmit.DeclareLocal(typeof(DbCommand)); var commandParameters = methodEmit.DeclareLocal(typeof(DbParameterCollection)); var queryBuilder = new StringBuilder("UPDATE " + mappingTable + " SET "); var objectNotDirtyLabel = methodEmit.DefineLabel(); foreach (var mappingInfo in properties.Values) { if (mappingInfo.MappingField != "Id") { queryBuilder.Append(mappingInfo.MappingField + "=@" + mappingInfo.MappingField + ", "); } } var tmpString = queryBuilder.ToString(0, queryBuilder.Length - 2); queryBuilder.Length = 0; queryBuilder.Append(tmpString); queryBuilder.Append(" WHERE Id = @Id"); methodEmit .ldarg_1 .call(typeof(IDbObject).GetMethod("get_IsDirty")) .brfalse(objectNotDirtyLabel) .ldc_i4_0 .stloc(resultLocal) .ldarg_2 .call(typeof(DbConnection).GetMethod("CreateCommand")) .stloc(commandLocal) .ldloc(commandLocal) .ldstr(queryBuilder.ToString()) .call(typeof(DbCommand).GetMethod("set_CommandText")) .ldloc(commandLocal) .call(typeof(DbCommand).GetMethod("get_Parameters")) .stloc(commandParameters); foreach (var mappingInfo in properties.Values) { var propertyInfo = mappingInfo.PropertyInfo; var mappingField = mappingInfo.MappingField; var propertyType = propertyInfo.PropertyType; if (propertyType.IsPrimitive || propertyType == typeof(string) || propertyType == typeof(DateTime) || propertyType == typeof(decimal)) { methodEmit .ldloc(commandParameters) .ldstr("@" + mappingField) //Param 1 for MySqlParameter constructor .ldarg_1 .call(propertyInfo.GetGetMethod()) //Param 2 for MySqlParameter constructor .newobj(typeof(MySqlParameter), typeof(string), typeof(object)) // Param for Add of DbParameterCollection .call(typeof(DbParameterCollection).GetMethod("Add", new[] { typeof(object) })) ; } else //Property that need to be convert to byte array before set { var propetyValueLocal = methodEmit.DeclareLocal(propertyType); var dbSerializerHelperLocal = methodEmit.DeclareLocal(typeof(DbSerializerHelper)); var memoryStreamLocal = methodEmit.DeclareLocal(typeof(MemoryStream)); var propertyByteArray = methodEmit.DeclareLocal(typeof(byte[])); methodEmit .ldarg_1 .call(propertyInfo.GetGetMethod()) .stloc(propetyValueLocal) .newobj(typeof(MemoryStream), Type.EmptyTypes) .stloc(memoryStreamLocal); methodEmit.BeginExceptionBlock(); methodEmit .ldloc(memoryStreamLocal) .newobj(typeof(BinaryWriter), typeof(Stream)) .newobj(typeof(DbSerializerHelper), typeof(BinaryWriter)) .stloc(dbSerializerHelperLocal) .ldloc(dbSerializerHelperLocal) .ldarg_1 .call(propertyInfo.GetGetMethod()) .call(typeof(DbSerializerHelper).GetMethod("Write", new[] { propertyType })) .ldloc(memoryStreamLocal) .call(typeof(MemoryStream).GetMethod("ToArray")) .stloc(propertyByteArray) .ldloc(commandParameters) .ldstr("@" + mappingField) .ldloc(propertyByteArray) .newobj(typeof(MySqlParameter), typeof(string), typeof(object)) // Param for Add of DbParameterCollection .call(typeof(DbParameterCollection).GetMethod("Add", new[] { typeof(object) })) .BeginFinallyBlock() .ldloc(memoryStreamLocal) .call(typeof(IDisposable).GetMethod("Dispose")) .EndExceptionBlock() ; } } methodEmit .ldloc(commandLocal) .call(typeof(DbCommand).GetMethod("ExecuteNonQuery")) .stloc(resultLocal) .ldarg_1 .ldc_bool(false) .call(typeof(IDbObject).GetMethod("set_IsDirty")) .MarkLabel(objectNotDirtyLabel); //Update relation var relations = classMetadata.RelationProperties; LocalBuilder queryExecutorLocal = null; if (relations.Count > 0) { queryExecutorLocal = methodEmit.DeclareLocal(typeof(IQueryExecutor)); var dbObjectContainerField = typeBuilderHelper.TypeBuilder.GetField("dbObjectContainer"); methodEmit .ldfld(dbObjectContainerField) .call(typeof(DbObjectContainer).GetMethod("get_QueryExecutor")) .stloc(queryExecutorLocal); } foreach (var relationInfo in relations.Values) { var propertyInfo = relationInfo.PropertyInfo; var propertyType = propertyInfo.PropertyType; var elementType = propertyType.IsGenericType ? propertyType.GetGenericArguments()[0] : propertyType; var listPersistentDbObjectLocal = methodEmit.DeclareLocal(typeof(IList <long>)); var listCurrentType = typeof(List <>).MakeGenericType(elementType); var addElementMethod = typeof(ICollection <>).MakeGenericType(elementType).GetMethod("Add"); var countElementMethod = typeof(ICollection <>).MakeGenericType(elementType).GetMethod("Count"); var listConstructorMethod = listCurrentType.GetConstructor(new[] { typeof(IEnumerable <>).MakeGenericType(elementType) }); var listCurrentDbObjectLocal = methodEmit.DeclareLocal(listCurrentType); var mappingColumn = relationInfo.PartnerKey; var relationCommandLocal = methodEmit.DeclareLocal(typeof(DbCommand)); var readerLocal = methodEmit.DeclareLocal(typeof(DbDataReader)); var relationTimeInfoLocal = methodEmit.DeclareLocal(typeof(TimeRelationInfo)); var commandText = "SELECT " + mappingColumn + " FROM " + mappingTable + " WHERE Id = @Id"; methodEmit .ldarg_2 .call(typeof(DbConnection).GetMethod("CreateCommand")) .stloc(relationCommandLocal) .ldloc(relationCommandLocal) .ldstr(commandText) .call(typeof(DbCommand).GetMethod("set_CommandText")) .ldloc(relationCommandLocal) .call(typeof(DbCommand).GetMethod("ExecuteReader")) .stloc(readerLocal) .ldstr(mappingColumn) .ldloc(readerLocal) .call(typeof(DbSerializerHelper).GetMethod("ReadRelationTimeInfo")) .stloc(relationTimeInfoLocal) .ldloc(relationTimeInfoLocal) .ldfld(typeof(TimeRelationInfo).GetField("idList")) .stloc(listPersistentDbObjectLocal) ; if (relationInfo.RelationKind == RelationInfo.RELATION_1_1) { methodEmit .newobj(listCurrentType, Type.EmptyTypes) .stloc(listCurrentDbObjectLocal) .ldloc(listCurrentDbObjectLocal) .ldarg_1 .call(propertyInfo.GetGetMethod()) .call(addElementMethod) ; } else { methodEmit .ldarg_1 .call(propertyInfo.GetGetMethod()) .newobj(listConstructorMethod) .stloc(listCurrentDbObjectLocal) ; } var lenLocal = methodEmit.DeclareLocal(typeof(int)); var iLocal = methodEmit.DeclareLocal(typeof(int)); var beginForLabel = methodEmit.DefineLabel(); var beginForBodyLabel = methodEmit.DefineLabel(); var itemLocal = methodEmit.DeclareLocal(elementType); var itemIdLocal = methodEmit.DeclareLocal(typeof(long)); var itemNullLabel = methodEmit.DefineLabel(); var getCurrentObjectElementMethod = listCurrentType.GetMethod("get_Item", new[] { typeof(int) }); var listPersistentContainCurrentElementLabel = methodEmit.DefineLabel(); var listPersistentNotContainCurrentElementLabel = methodEmit.DefineLabel(); methodEmit .ldloc(listCurrentDbObjectLocal) .call(countElementMethod) .stloc(lenLocal) .ldc_i4_0 .stloc(iLocal) .br(beginForLabel) .MarkLabel(beginForBodyLabel) .ldloc(listCurrentDbObjectLocal) .ldloc(iLocal) .call(getCurrentObjectElementMethod) .stloc(itemLocal) .ldloc(itemLocal) .brfalse(itemNullLabel) .ldloc(itemLocal) .call(typeof(IDbObject).GetMethod("get_Id")) .stloc(itemIdLocal) .ldloc(listPersistentDbObjectLocal) .ldloc(itemIdLocal) .call(typeof(ICollection <long>).GetMethod("Contain")) .brtrue(listPersistentContainCurrentElementLabel) .ldloc(queryExecutorLocal) .ldloc(itemLocal) .ldnull .call(typeof(IQueryExecutor).GetMethod("Insert", new[] { typeof(IDbObject), typeof(IsolationLevel?), typeof(long), typeof(string) })) .br(listPersistentNotContainCurrentElementLabel) .MarkLabel(listPersistentContainCurrentElementLabel) .MarkLabel(listPersistentNotContainCurrentElementLabel) .MarkLabel(itemNullLabel) .ldloc(iLocal) .ldc_i4_1 .add .stloc(iLocal) .MarkLabel(beginForLabel) .ldloc(iLocal) .ldloc(lenLocal) .blt(beginForBodyLabel) ; } }
private static Type EnsureDelegateType(BuildContext context, MethodInfo method) { // The delegate should be defined as inner type of context.TypeBuilder. // It's possible, but we can not define and use newly defined type as Emit target in its owner type. // To solve this problem, we should create a top level delegate and make sure its name is unique. // string delegateName = context.TypeBuilder.TypeBuilder.FullName + "$" + method.Name + "$Delegate"; Type delegateType = (Type)context.Items[delegateName]; if (delegateType == null) { ParameterInfo[] pi = method.GetParameters(); Type[] parameters = new Type[pi.Length]; for (int i = 0; i < pi.Length; i++) { parameters[i] = pi[i].ParameterType; } const MethodImplAttributes mia = MethodImplAttributes.Runtime | MethodImplAttributes.Managed; const MethodAttributes ma = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual; TypeBuilderHelper delegateBuilder = context.AssemblyBuilder.DefineType(delegateName, TypeAttributes.Class | TypeAttributes.NotPublic | TypeAttributes.Sealed | TypeAttributes.AnsiClass | TypeAttributes.AutoClass, typeof(MulticastDelegate)); // Create constructor // ConstructorBuilderHelper ctorBuilder = delegateBuilder.DefineConstructor( MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.RTSpecialName, CallingConventions.Standard, typeof(object), typeof(IntPtr)); ctorBuilder.ConstructorBuilder.SetImplementationFlags(mia); MethodBuilderHelper methodBuilder; // Define the BeginInvoke method for the delegate // Type[] beginParameters = new Type[parameters.Length + 2]; Array.Copy(parameters, 0, beginParameters, 0, parameters.Length); beginParameters[parameters.Length] = typeof(AsyncCallback); beginParameters[parameters.Length + 1] = typeof(object); methodBuilder = delegateBuilder.DefineMethod("BeginInvoke", ma, typeof(IAsyncResult), beginParameters); methodBuilder.MethodBuilder.SetImplementationFlags(mia); // Define the EndInvoke method for the delegate // methodBuilder = delegateBuilder.DefineMethod("EndInvoke", ma, method.ReturnType, typeof(IAsyncResult)); methodBuilder.MethodBuilder.SetImplementationFlags(mia); // Define the Invoke method for the delegate // methodBuilder = delegateBuilder.DefineMethod("Invoke", ma, method.ReturnType, parameters); methodBuilder.MethodBuilder.SetImplementationFlags(mia); context.Items[delegateName] = delegateType = delegateBuilder.Create(); } return(delegateType); }
private void BuildGetter(MemberInfo mi, TypeBuilderHelper nestedType) { var methodType = mi.DeclaringType; var getMethod = null as MethodInfo; if (mi is PropertyInfo) { getMethod = ((PropertyInfo)mi).GetGetMethod(); if (getMethod == null) { if (_type != _originalType) { getMethod = _type.GetMethod("get_" + mi.Name); methodType = _type; } if (getMethod == null || !IsMethodAccessible(getMethod)) return; } } var method = nestedType.DefineMethod(_memberAccessor.GetMethod("GetValue", typeof(object))); var emit = method.Emitter; emit .ldarg_1 .castType (methodType) .end(); if (mi is FieldInfo) { var fi = (FieldInfo)mi; emit .ldfld (fi) .boxIfValueType (fi.FieldType) ; } else { if (methodType.IsValueType) { var loc = emit.DeclareLocal(methodType); emit .stloc ((byte)loc.LocalIndex) .ldloca_s ((byte)loc.LocalIndex); } var pi = (PropertyInfo)mi; emit .callvirt (getMethod) .boxIfValueType (pi.PropertyType) ; } emit .ret() ; nestedType.DefineMethod(_memberAccessor.GetProperty("HasGetter").GetGetMethod()).Emitter .ldc_i4_1 .ret() ; }
private void BuildGetter(MemberInfo mi, TypeBuilderHelper nestedType) { var methodType = mi.DeclaringType; var getMethod = null as MethodInfo; if (mi is PropertyInfo) { getMethod = ((PropertyInfo)mi).GetGetMethod(); if (getMethod == null) { if (_type != _originalType) { getMethod = _type.GetMethod("get_" + mi.Name); methodType = _type; } if (getMethod == null || !IsMethodAccessible(getMethod)) { return; } } } var method = nestedType.DefineMethod(_memberAccessor.GetMethod("GetValue", typeof(object))); var emit = method.Emitter; emit .ldarg_1 .castType(methodType) .end(); if (mi is FieldInfo) { var fi = (FieldInfo)mi; emit .ldfld(fi) .boxIfValueType(fi.FieldType) ; } else { if (methodType.IsValueType) { var loc = emit.DeclareLocal(methodType); emit .stloc((byte)loc.LocalIndex) .ldloca_s((byte)loc.LocalIndex); } var pi = (PropertyInfo)mi; emit .callvirt(getMethod) .boxIfValueType(pi.PropertyType) ; } emit .ret() ; nestedType.DefineMethod(_memberAccessor.GetProperty("HasGetter").GetGetMethod()).Emitter .ldc_i4_1 .ret() ; }
private void BuildIsNull( MemberInfo mi, TypeBuilderHelper nestedType, Type memberType) { var methodType = mi.DeclaringType; var getMethod = null as MethodInfo; var isNullable = TypeHelper.IsNullable(memberType); var isValueType = (!isNullable && memberType.IsValueType); if (!isValueType && mi is PropertyInfo) { getMethod = ((PropertyInfo)mi).GetGetMethod(); if (getMethod == null) { if (_type != _originalType) { getMethod = _type.GetMethod("get_" + mi.Name); methodType = _type; } if (getMethod == null) return; } } var methodInfo = _memberAccessor.GetMethod("IsNull"); if (methodInfo == null) return; var method = nestedType.DefineMethod(methodInfo); var emit = method.Emitter; if (isValueType) { emit .ldc_i4_0 .end() ; } else { LocalBuilder locObj = null; if (isNullable) locObj = method.Emitter.DeclareLocal(memberType); emit .ldarg_1 .castType (methodType) .end(); if (mi is FieldInfo) emit.ldfld ((FieldInfo)mi); else emit.callvirt(getMethod); if (isNullable) { emit .stloc(locObj) .ldloca(locObj) .call(memberType, "get_HasValue") .ldc_i4_0 .ceq .end(); } else { emit .ldnull .ceq .end(); } } emit .ret() ; }
private void BuildSetter(MemberInfo mi, TypeBuilderHelper nestedType) { var methodType = mi.DeclaringType; var setMethod = null as MethodInfo; if (mi is PropertyInfo) { setMethod = ((PropertyInfo)mi).GetSetMethod(); if (setMethod == null) { if (_type != _originalType) { setMethod = _type.GetMethod("set_" + mi.Name); methodType = _type; } if (setMethod == null || !IsMethodAccessible(setMethod)) { return; } } } //else if (((FieldInfo)mi).IsLiteral) // return; var method = nestedType.DefineMethod(_memberAccessor.GetMethod("SetValue", typeof(object), typeof(object))); var emit = method.Emitter; emit .ldarg_1 .castType(methodType) .ldarg_2 .end(); if (mi is FieldInfo) { var fi = (FieldInfo)mi; emit .CastFromObject(fi.FieldType) .stfld(fi) ; } else { var pi = (PropertyInfo)mi; emit .CastFromObject(pi.PropertyType) .callvirt(setMethod) ; } emit .ret() ; nestedType.DefineMethod(_memberAccessor.GetProperty("HasSetter").GetGetMethod()).Emitter .ldc_i4_1 .ret() ; }
private void BuildCloneValueMethod( MemberInfo mi, TypeBuilderHelper nestedType, Type memberType ) { var methodType = mi.DeclaringType; var getMethod = null as MethodInfo; var setMethod = null as MethodInfo; if (mi is PropertyInfo) { getMethod = ((PropertyInfo)mi).GetGetMethod(); if (getMethod == null) { if (_type != _originalType) { getMethod = _type.GetMethod("get_" + mi.Name); methodType = _type; } if (getMethod == null || !IsMethodAccessible(getMethod)) return; } setMethod = ((PropertyInfo)mi).GetSetMethod(); if (setMethod == null) { if (_type != _originalType) { setMethod = _type.GetMethod("set_" + mi.Name); methodType = _type; } if (setMethod == null || !IsMethodAccessible(setMethod)) return; } } var method = nestedType.DefineMethod(_memberAccessor.GetMethod("CloneValue", typeof(object), typeof(object))); var emit = method.Emitter; emit .ldarg_2 .castType (methodType) .ldarg_1 .castType (methodType) .end(); if (mi is FieldInfo) emit.ldfld ((FieldInfo)mi); else emit.callvirt(getMethod); if (typeof(string) != memberType && TypeHelper.IsSameOrParent(typeof(ICloneable), memberType)) { if (memberType.IsValueType) emit .box (memberType) .callvirt (typeof(ICloneable), "Clone") .unbox_any (memberType) ; else { var valueIsNull = emit.DefineLabel(); emit .dup .brfalse_s (valueIsNull) .callvirt (typeof(ICloneable), "Clone") .castclass (memberType) .MarkLabel (valueIsNull) ; } } if (mi is FieldInfo) emit.stfld ((FieldInfo)mi); else emit.callvirt(setMethod); emit .ret() ; }
private void BuildIsNull( MemberInfo mi, TypeBuilderHelper nestedType, Type memberType) { var methodType = mi.DeclaringType; var getMethod = null as MethodInfo; var isNullable = TypeHelper.IsNullable(memberType); var isValueType = (!isNullable && memberType.IsValueType); if (!isValueType && mi is PropertyInfo) { getMethod = ((PropertyInfo)mi).GetGetMethod(); if (getMethod == null) { if (_type != _originalType) { getMethod = _type.GetMethod("get_" + mi.Name); methodType = _type; } if (getMethod == null) { return; } } } var methodInfo = _memberAccessor.GetMethod("IsNull"); if (methodInfo == null) { return; } var method = nestedType.DefineMethod(methodInfo); var emit = method.Emitter; if (isValueType) { emit .ldc_i4_0 .end() ; } else { LocalBuilder locObj = null; if (isNullable) { locObj = method.Emitter.DeclareLocal(memberType); } emit .ldarg_1 .castType(methodType) .end(); if (mi is FieldInfo) { emit.ldfld((FieldInfo)mi); } else { emit.callvirt(getMethod); } if (isNullable) { emit .stloc(locObj) .ldloca(locObj) .call(memberType, "get_HasValue") .ldc_i4_0 .ceq .end(); } else { emit .ldnull .ceq .end(); } } emit .ret() ; }
private void BuildTypedSetterForNullable( MemberInfo mi, TypeBuilderHelper nestedType, Type memberType) { var methodType = mi.DeclaringType; var setMethod = null as MethodInfo; if (mi is PropertyInfo) { setMethod = ((PropertyInfo)mi).GetSetMethod(); if (setMethod == null) { if (_type != _originalType) { setMethod = _type.GetMethod("set_" + mi.Name); methodType = _type; } if (setMethod == null || !IsMethodAccessible(setMethod)) return; } } var setterType = (memberType.IsEnum ? Enum.GetUnderlyingType(memberType) : memberType); var methodInfo = _memberAccessor.GetMethod("Set" + setterType.Name, typeof(object), setterType); if (methodInfo == null) return; var method = nestedType.DefineMethod(methodInfo); var emit = method.Emitter; emit .ldarg_1 .castType (methodType) .ldarg_2 .newobj (typeof(Nullable<>).MakeGenericType(memberType), memberType) .end(); if (mi is FieldInfo) emit.stfld ((FieldInfo)mi); else emit.callvirt(setMethod); emit .ret() ; }
private bool BuildMembers(Type interfaceType) { FieldInfo objectField = typeof(DuckType).GetField("_object", BindingFlags.NonPublic | BindingFlags.Instance); BindingFlags flags = BindingFlags.Public | BindingFlags.Instance | (DuckTyping.AllowStaticMembers? BindingFlags.Static | BindingFlags.FlattenHierarchy: 0); foreach (MethodInfo interfaceMethod in interfaceType.GetMethods(BindingFlags.Public | BindingFlags.Instance)) { ParameterInfo[] ips = interfaceMethod.GetParameters(); MethodInfo targetMethod = null; foreach (MethodInfo mi in _objectType.GetMethods(flags)) { ParameterInfo[] ops = mi.GetParameters(); if (mi.Name == interfaceMethod.Name && mi.ReturnType == interfaceMethod.ReturnType && ops.Length == ips.Length) { targetMethod = mi; for (int i = 0; i < ips.Length && targetMethod != null; i++) { ParameterInfo ip = ips[i]; ParameterInfo op = ops[i]; if (ip.ParameterType != op.ParameterType || ip.IsIn != op.IsIn || ip.IsOut != op.IsOut) { targetMethod = null; } } if (targetMethod != null) { break; } } } MethodBuilderHelper builder = _typeBuilder.DefineMethod(interfaceMethod); EmitHelper emit = builder.Emitter; if (targetMethod != null) { if (!targetMethod.IsStatic) { emit .ldarg_0 .ldfld(objectField) ; if (_objectType.IsValueType) { // For value types we have to use stack. // LocalBuilder obj = emit.DeclareLocal(_objectType); emit .unbox_any(_objectType) .stloc(obj) .ldloca(obj) ; } else { emit .castclass(_objectType) ; } } foreach (ParameterInfo p in interfaceMethod.GetParameters()) { emit.ldarg(p); } if (targetMethod.IsStatic) { emit .call(targetMethod) .ret(); } else { emit .callvirt(targetMethod) .ret(); } } else { // Method or property was not found. // Insert an empty stub or stub that throws the NotImplementedException. // MustImplementAttribute attr = (MustImplementAttribute) Attribute.GetCustomAttribute(interfaceMethod, typeof(MustImplementAttribute)); if (attr == null) { attr = (MustImplementAttribute)Attribute.GetCustomAttribute( interfaceMethod.DeclaringType, typeof(MustImplementAttribute)); if (attr == null) { attr = MustImplementAttribute.Default; } } // When the member is marked as 'Required' throw a build-time exception. // if (attr.Implement) { if (attr.ThrowException) { throw new TypeBuilderException(string.Format( Resources.TypeBuilder_PublicMethodMustBeImplemented, _objectType.FullName, interfaceMethod)); } else { // Implement == true, but ThrowException == false. // In this case the null pointer will be returned. // This mimics the 'as' operator behaviour. // return(false); } } if (attr.ThrowException) { string message = attr.ExceptionMessage; if (message == null) { message = string.Format(Resources.TypeBuilder_PublicMethodNotImplemented, _objectType.FullName, interfaceMethod); } emit .ldstr(message) .newobj(typeof(NotImplementedException), typeof(string)) .@throw .end(); } else { // Emit a 'do nothing' stub. // LocalBuilder returnValue = null; if (interfaceMethod.ReturnType != typeof(void)) { returnValue = emit.DeclareLocal(interfaceMethod.ReturnType); emit.Init(returnValue); } // Initialize out parameters. // ParameterInfo[] parameters = interfaceMethod.GetParameters(); if (parameters != null) { emit.InitOutParameters(parameters); } if (returnValue != null) { emit.ldloc(returnValue); } emit.ret(); } } } return(true); }