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() ; }
protected bool CallLazyInstanceInsurer(FieldBuilder field) { if (field == null) { throw new ArgumentNullException("field"); } MethodBuilderHelper ensurer = Context.GetFieldInstanceEnsurer(field.Name); if (ensurer != null) { Context.MethodBuilder.Emitter .ldarg_0 .call(ensurer); } return(ensurer != null); }
private void BuildLazyInstanceEnsurer() { string fieldName = GetFieldName(); FieldBuilder field = Context.GetField(fieldName); TypeHelper fieldType = new TypeHelper(field.FieldType); TypeHelper objectType = new TypeHelper(GetObjectType()); MethodBuilderHelper ensurer = Context.TypeBuilder.DefineMethod( string.Format("$EnsureInstance{0}", fieldName), MethodAttributes.Private | MethodAttributes.HideBySig); EmitHelper emit = ensurer.Emitter; Label end = emit.DefineLabel(); emit .ldarg_0 .ldfld(field) .brtrue_s(end) ; object[] parameters = TypeHelper.GetPropertyParameters(Context.CurrentProperty); ConstructorInfo ci = objectType.GetPublicConstructor(typeof(InitContext)); if (ci != null || objectType.IsAbstract) { CreateInitContextLazyInstance(field, fieldType, objectType, emit, parameters); } else if (parameters == null) { CreateDefaultInstance(field, fieldType, objectType, emit); } else { CreateParametrizedInstance(field, fieldType, objectType, emit, parameters); } emit .MarkLabel(end) .ret() ; Context.Items.Add("$BLToolkit.FieldInstanceEnsurer." + fieldName, ensurer); }
private void BuildTypeProperties() { // Type. // MethodBuilderHelper method = _typeBuilder.DefineMethod(_accessorType.GetProperty("Type").GetGetMethod()); method.Emitter .LoadType(_type) .ret() ; // OriginalType. // method = _typeBuilder.DefineMethod(_accessorType.GetProperty("OriginalType").GetGetMethod()); method.Emitter .LoadType(_originalType) .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); }
public void Test() { TypeBuilderHelper typeBuilder = new AssemblyBuilderHelper("HelloWorld.dll").DefineType("Test", typeof(TestObject)); // Property // PropertyInfo propertyInfo = typeof(TestObject).GetProperty("Property"); MethodBuilderHelper methodBuilder = typeBuilder.DefineMethod(propertyInfo.GetGetMethod()); EmitHelper emit = methodBuilder.Emitter; emit .ldc_i4(10) .ret() ; // Method1 // MethodInfo methodInfo = typeof(TestObject).GetMethod( "Method1", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); methodBuilder = typeBuilder.DefineMethod(methodInfo); emit = methodBuilder.Emitter; emit .ldc_i4(10) .ret() ; // Method2 // methodInfo = typeof(TestObject).GetMethod("Method2", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); methodBuilder = typeBuilder.DefineMethod( "Method2", MethodAttributes.Virtual | MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.PrivateScope | MethodAttributes.VtableLayoutMask, typeof(int), new Type[] { typeof(float) }); typeBuilder.TypeBuilder.DefineMethodOverride(methodBuilder, methodInfo); emit = methodBuilder.Emitter; emit .ldc_i4(10) .ret() ; // Create type. // Type type = typeBuilder.Create(); TestObject obj = (TestObject)Activator.CreateInstance(type); Assert.AreEqual(10, obj.Property); Assert.AreEqual(10, obj.Method3(0)); Assert.AreEqual(10, obj.Method2(0)); }
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); // 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); MethodBuilderHelper 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 BuildTypedGetterForNullable( MemberInfo mi, TypeBuilderHelper nestedType, Type memberType) { 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; } } } Type setterType = (memberType.IsEnum ? Enum.GetUnderlyingType(memberType) : memberType); MethodInfo methodInfo = _memberAccessor.GetMethod("Get" + setterType.Name, typeof(object)); if (methodInfo == null) { return; } MethodBuilderHelper method = nestedType.DefineMethod(methodInfo); Type nullableType = typeof(Nullable <>).MakeGenericType(memberType); EmitHelper emit = method.Emitter; emit .ldarg_1 .castType(methodType) .end(); if (mi is FieldInfo) { emit.ldflda((FieldInfo)mi); } else { LocalBuilder 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 ) { Type methodType = mi.DeclaringType; MethodInfo getMethod = null; MethodInfo setMethod = 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; } } setMethod = ((PropertyInfo)mi).GetSetMethod(); if (setMethod == null) { if (_type != _originalType) { setMethod = _type.GetMethod("set_" + mi.Name); methodType = _type; } if (setMethod == null || !IsMethodAccessible(setMethod)) { return; } } } MethodBuilderHelper method = nestedType.DefineMethod( _memberAccessor.GetMethod("CloneValue", typeof(object), typeof(object))); EmitHelper 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 { Label 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) { Type methodType = mi.DeclaringType; MethodInfo getMethod = null; Boolean isNullable = TypeHelper.IsNullable(memberType); Boolean 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; } } } MethodInfo methodInfo = _memberAccessor.GetMethod("IsNull"); if (methodInfo == null) { return; } MethodBuilderHelper method = nestedType.DefineMethod(methodInfo); EmitHelper 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) { 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; } } } //else if (((FieldInfo)mi).IsLiteral) // return; MethodBuilderHelper method = nestedType.DefineMethod( _memberAccessor.GetMethod("SetValue", typeof(object), typeof(object))); EmitHelper emit = method.Emitter; emit .ldarg_1 .castType(methodType) .ldarg_2 .end(); if (mi is FieldInfo) { FieldInfo fi = (FieldInfo)mi; emit .CastFromObject(fi.FieldType) .stfld(fi) ; } else { PropertyInfo 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) { 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() ; }
void BuildCreateInstanceMethods() { bool isValueType = _type.IsValueType; ConstructorInfo baseDefCtor = isValueType? null: _type.GetPublicDefaultConstructor(); ConstructorInfo baseInitCtor = _type.GetPublicConstructor(typeof(InitContext)); if (baseDefCtor == null && baseInitCtor == null && !isValueType) { return; } // CreateInstance. // MethodBuilderHelper method = _typeBuilder.DefineMethod( _accessorType.GetMethod(false, "CreateInstance", Type.EmptyTypes)); if (baseDefCtor != null) { method.Emitter .newobj(baseDefCtor) .ret() ; } else if (isValueType) { LocalBuilder 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) { LocalBuilder 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 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); }