public Tuple <Type, Func <object> > CreateProxyType(Type t, bool compileProxyContructor = true) { Type interceptorType; Type typeToDerive = t; bool genericType = false; GeneratedTypeKey key = new GeneratedTypeKey(typeToDerive); Tuple <Type, Func <object> > tuple; if (DerivedClasses.TryGetValue(key, out tuple)) { return(tuple); } if (t.IsGenericType) { typeToDerive = t.GetGenericTypeDefinition(); genericType = true; } if (!CanIntercept(t)) { throw new InvalidOperationException( string.Format(CultureInfo.CurrentCulture, Resources.InterceptionNotSupported, t.Name)); } lock (DerivedClasses) { InterceptingClassGenerator generator = new InterceptingClassGenerator(typeToDerive); interceptorType = generator.GenerateType(); if (genericType) { interceptorType = interceptorType.MakeGenericType(t.GetGenericArguments()); } Func <object> contructor = null; if (compileProxyContructor) { contructor = Expression.Lambda <Func <object> >(Expression.New(interceptorType)).Compile(); } tuple = new Tuple <Type, Func <object> >(interceptorType, contructor); DerivedClasses[key] = tuple; } if (genericType) { IList <PropertyInfoEx> tableInfo; TypePropertiesCache.VerifyInformationIsLoaded(interceptorType, out tableInfo); } else { TypePropertiesCache.AssociateTypeWithProxyType(t, interceptorType); } PropertiesExDictionary dic; TypePropertiesCache.cachePropertiesEx.TryGetValue(interceptorType, out dic); interceptorType.GetField("__Props").SetValue(null, (PropertyInfoEx[])dic.PropertiesList); //PropertyInfoEx[] currentProps; //TypePropertiesCache.cachePropertiesEx.TryGetValue(t, out currentProps); //TypePropertiesCache.cachePropertiesEx.Remove(t); //TypePropertiesCache.cachePropertiesEx.Add(interceptorType, currentProps); return(tuple); }
/// <summary> /// Create the wrapper class for the given type. /// </summary> /// <returns>Wrapper type.</returns> public Type GenerateType() { var props = TypePropertiesCache.GetArrayPropertiesOrderedByIndex(typeToIntercept); AddProperties(props); AddConstructors(); ConstructorBuilder staticConstructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, Type.EmptyTypes); ILGenerator staticConstructorILGenerator = staticConstructorBuilder.GetILGenerator(); foreach (var method in methodOverrides) { if (method.statficfieldForMethodHandle != null) { staticConstructorILGenerator.Emit(OpCodes.Ldtoken, method.methodInfoForMethodHandle); if (method.methodToOverride.DeclaringType.IsGenericType) { // if the declaring type is generic, we need to get the method from the target type staticConstructorILGenerator.Emit(OpCodes.Ldtoken, method.targetType); staticConstructorILGenerator.Emit(OpCodes.Call, MethodBaseMethods.GetMethodForGenericFromHandle); } else { staticConstructorILGenerator.Emit(OpCodes.Call, MethodBaseMethods.GetMethodFromHandle); // target method } } staticConstructorILGenerator.Emit(OpCodes.Stsfld, method.statficfieldForMethodHandle); } staticConstructorILGenerator.Emit(OpCodes.Ret); Type result = typeBuilder.CreateType(); return(result); }