public Type Build(AssemblyBuilderHelper assemblyBuilder) { if (assemblyBuilder == null) throw new ArgumentNullException("assemblyBuilder"); // Check InternalsVisibleToAttributes of the source type's assembly. // Even if the sourceType is public, it may have internal fields and props. // _friendlyAssembly = false; // Usually, there is no such attribute in the source assembly. // Therefore we do not cache the result. // var attributes = _originalType.Type.Assembly.GetCustomAttributes(typeof(InternalsVisibleToAttribute), true); foreach (InternalsVisibleToAttribute visibleToAttribute in attributes) { var an = new AssemblyName(visibleToAttribute.AssemblyName); if (AssemblyName.ReferenceMatchesDefinition(assemblyBuilder.AssemblyName, an)) { _friendlyAssembly = true; break; } } if (!_originalType.Type.IsVisible && !_friendlyAssembly) return typeof (ExprTypeAccessor<,>).MakeGenericType(_type, _originalType); var typeName = GetTypeName(); _typeBuilder = assemblyBuilder.DefineType(typeName, _accessorType); _typeBuilder.DefaultConstructor.Emitter .ldarg_0 .call (TypeHelper.GetDefaultConstructor(_accessorType)) ; BuildCreateInstanceMethods(); BuildTypeProperties(); BuildMembers(); BuildObjectFactory(); _typeBuilder.DefaultConstructor.Emitter .ret() ; var result = _typeBuilder.Create(); foreach (TypeBuilderHelper tb in _nestedTypes) tb.Create(); return result; }
private static ConstructorBuilderHelper BuildNestedTypeConstructor(TypeBuilderHelper nestedType) { Type[] parameters = { typeof(TypeAccessor), typeof(MemberInfo) }; var ctorBuilder = nestedType.DefinePublicConstructor(parameters); ctorBuilder.Emitter .ldarg_0 .ldarg_1 .ldarg_2 .call (TypeHelper.GetConstructor(typeof(MemberAccessor), parameters)) .ret() ; return ctorBuilder; }
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 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 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 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 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() ; }