protected Type CreateConstructorType(AccessorClassLoader loader, String constructorClassName, Type delegateType, Type targetType) { if (Log.DebugEnabled) { Log.Debug("Creating fast constructor handle for " + targetType.FullName); } Type delegateTypeHandle = delegateType; Type objType = typeof(Object); Type superType; TypeBuilder cw; if (delegateType.IsInterface) { superType = objType; cw = loader.CreateNewType(TypeAttributes.Public, constructorClassName, superType, new Type[] { delegateTypeHandle }); } else { superType = delegateTypeHandle; cw = loader.CreateNewType(TypeAttributes.Public, constructorClassName, superType, Type.EmptyTypes); } { ConstructorInfo baseConstructor = superType.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null); if (baseConstructor == null) { throw new Exception("Constructor not found: " + superType.FullName); } ILGenerator mv = cw.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, Type.EmptyTypes).GetILGenerator(); mv.Emit(OpCodes.Ldarg_0); mv.Emit(OpCodes.Call, baseConstructor); mv.Emit(OpCodes.Ret); } MethodInfo[] r_methods = ReflectUtil.GetMethods(delegateType); ConstructorInfo[] constructors = targetType.GetConstructors(); foreach (ConstructorInfo constructor in constructors) { ParameterInfo[] constructorParams = constructor.GetParameters(); for (int a = r_methods.Length; a-- > 0;) { MethodInfo r_method = r_methods[a]; if (r_method == null) { // already handled continue; } if (!delegateType.IsInterface && !r_method.IsAbstract) { // only handle abstract methods r_methods[a] = null; continue; } ParameterInfo[] methodParams = r_method.GetParameters(); if (constructorParams.Length != methodParams.Length) { // no match continue; } bool paramsEqual = true; for (int b = constructorParams.Length; b-- > 0;) { if (!constructorParams[b].ParameterType.Equals(methodParams[b].ParameterType)) { paramsEqual = false; break; } } if (!paramsEqual) { // no match continue; } r_methods[a] = null; ImplementConstructorOfConstructorType(r_method, constructor, cw); } } foreach (MethodInfo r_method in r_methods) { if (r_method != null) { throw new ArgumentException("No matching constructor found on " + targetType.FullName + " to map on delegate method " + r_method.ToString()); } } return(loader.GetType(constructorClassName, cw)); }
protected Type CreateType(AccessorClassLoader loader, String accessClassName, Type targetType, IPropertyInfo property) { if (Log.DebugEnabled) { Log.Debug("Creating accessor for " + targetType.FullName + "." + property.Name); } Type abstractAccessorType = typeof(AbstractAccessor); Type objType = typeof(Object); TypeBuilder cw = loader.CreateNewType(TypeAttributes.Public, accessClassName, abstractAccessorType, Type.EmptyTypes); { ConstructorInfo baseConstructor = abstractAccessorType.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] { typeof(Type), typeof(String) }, null); ILGenerator mv = cw.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, new Type[] { typeof(Type), typeof(String) }).GetILGenerator(); mv.Emit(OpCodes.Ldarg_0); mv.Emit(OpCodes.Ldarg_1); mv.Emit(OpCodes.Ldarg_2); mv.Emit(OpCodes.Call, baseConstructor); mv.Emit(OpCodes.Ret); } MethodInfo r_get = ReflectUtil.GetDeclaredMethod(true, targetType, property.PropertyType, "get_" + property.Name, new Type[0]); if (r_get == null) { r_get = ReflectUtil.GetDeclaredMethod(true, targetType, property.PropertyType, "Get" + property.Name, new Type[0]); } if (r_get == null) { r_get = ReflectUtil.GetDeclaredMethod(true, targetType, property.PropertyType, "Is" + property.Name, new Type[0]); } MethodInfo r_set = ReflectUtil.GetDeclaredMethod(true, targetType, property.PropertyType, "set_" + property.Name, new Type[] { null }); if (r_set == null) { r_set = ReflectUtil.GetDeclaredMethod(true, targetType, property.PropertyType, "Set" + property.Name, new Type[] { null }); } { ILGenerator mv = cw.DefineMethod("get_CanRead", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig, CallingConventions.HasThis, typeof(bool), Type.EmptyTypes).GetILGenerator(); mv.Emit(r_get != null && r_get.IsPublic ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0); mv.Emit(OpCodes.Ret); } { ILGenerator mv = cw.DefineMethod("get_CanWrite", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig, CallingConventions.HasThis, typeof(bool), Type.EmptyTypes).GetILGenerator(); mv.Emit(r_set != null && r_set.IsPublic ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0); mv.Emit(OpCodes.Ret); } { ILGenerator mv = cw.DefineMethod("GetValue", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig, CallingConventions.HasThis, typeof(Object), new Type[] { typeof(Object) }).GetILGenerator(); if (r_get == null) { mv.Emit(OpCodes.Ldstr, "Property not readable: " + targetType.FullName + "." + property.Name); mv.ThrowException(typeof(NotSupportedException)); } else { Type owner = r_get.DeclaringType; mv.Emit(OpCodes.Ldarg_1); mv.Emit(OpCodes.Castclass, owner); mv.Emit(OpCodes.Callvirt, r_get); if (r_get.ReturnType.IsValueType) { mv.Emit(OpCodes.Box, r_get.ReturnType); } } mv.Emit(OpCodes.Ret); } { MethodAttributes access = MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig; access |= MethodAttributes.ReuseSlot; access &= ~MethodAttributes.VtableLayoutMask; ILGenerator mv = cw.DefineMethod("SetValue", access, CallingConventions.HasThis, typeof(void), new Type[] { typeof(Object), typeof(Object) }).GetILGenerator(); if (r_set == null) { mv.Emit(OpCodes.Ldstr, "Property not writable: " + targetType.FullName + "." + property.Name); mv.ThrowException(typeof(NotSupportedException)); } else { Type owner = r_get.DeclaringType; mv.Emit(OpCodes.Ldarg_1); mv.Emit(OpCodes.Castclass, owner); mv.Emit(OpCodes.Ldarg_2); Type paramType = r_set.GetParameters()[0].ParameterType; if (!objType.Equals(paramType)) { if (paramType.IsValueType) { mv.Emit(OpCodes.Unbox_Any, paramType); } else { mv.Emit(OpCodes.Castclass, paramType); } } mv.Emit(OpCodes.Callvirt, r_set); } mv.Emit(OpCodes.Ret); } return(loader.GetType(accessClassName, cw)); }