/// <summary> /// Initializes a new instance of the AdapterBuilderContext class. /// </summary> /// <param name="originalObject"></param> /// <param name="classEmitter"></param> /// <param name="adaptedObjectRef"></param> public AdapterBuilderStageContext(Type originalObject, ClassEmitter classEmitter, FieldReference adaptedObjectRef, MethodInfo originalMethod) { OriginalObject = originalObject; ClassEmitter = classEmitter; AdaptedObjectRef = adaptedObjectRef; OriginalMethod = originalMethod; }
protected void ImplementProxyTargetAccessor(ClassEmitter emitter, FieldReference interceptorsField) { var dynProxyGetTarget = emitter.CreateMethod("DynProxyGetTarget", typeof(object)); dynProxyGetTarget.CodeBuilder.AddStatement( new ReturnStatement(new ConvertExpression(typeof(object), targetType, GetTargetReferenceExpression(emitter)))); var getInterceptors = emitter.CreateMethod("GetInterceptors", typeof(IInterceptor[])); getInterceptors.CodeBuilder.AddStatement( new ReturnStatement(interceptorsField)); }
/// <summary> /// Creates an intercepted property named __metadata, which only has a setter, which is used to deserialize /// the document metadata. Since there is no getter, it won't be serialized back to the data store. /// </summary> private void CreateMetadataProperty(ClassEmitter emitter, FieldReference interceptorsField) { var propertyBuilder = emitter.TypeBuilder.DefineProperty("__metadata", PropertyAttributes.None, CallingConventions.HasThis, typeof (DocumentMetadata), null, null, null, null, null); var methodBuilder = emitter.TypeBuilder.DefineMethod("set___metadata", MethodAttributes.Public | MethodAttributes.SpecialName); methodBuilder.SetParameters(typeof (DocumentMetadata)); var codeBuilder = methodBuilder.GetILGenerator(); codeBuilder.Emit(OpCodes.Ldarg_0); codeBuilder.Emit(OpCodes.Ldfld, interceptorsField.Fieldbuilder); codeBuilder.Emit(OpCodes.Ldc_I4_0); codeBuilder.Emit(OpCodes.Ldelem, typeof(IInterceptor)); codeBuilder.Emit(OpCodes.Castclass, typeof(DocumentProxyInterceptor)); codeBuilder.Emit(OpCodes.Ldarg_1); codeBuilder.Emit(OpCodes.Call, SetMetadata); codeBuilder.Emit(OpCodes.Ret); propertyBuilder.SetSetMethod(methodBuilder); }
protected MethodEmitter ImplementProxiedMethod( Type targetType, MethodEmitter methodEmitter, MethodInfo method, ClassEmitter emitter, NestedClassEmitter invocationImpl, FieldReference interceptorsField, Reference targetRef, ConstructorVersion version, MethodInfo methodOnTarget) { CheckNotGenericTypeDefinition(targetType, "targetType"); methodEmitter.CopyParametersAndReturnTypeFrom(method, emitter); TypeReference[] dereferencedArguments = IndirectReference.WrapIfByRef(methodEmitter.Arguments); Type iinvocation = invocationImpl.TypeBuilder; Trace.Assert(method.IsGenericMethod == iinvocation.IsGenericTypeDefinition); bool isGenericInvocationClass = false; Type[] genericMethodArgs = new Type[0]; if (method.IsGenericMethod) { // bind generic method arguments to invocation's type arguments genericMethodArgs = methodEmitter.MethodBuilder.GetGenericArguments(); iinvocation = iinvocation.MakeGenericType(genericMethodArgs); isGenericInvocationClass = true; } LocalReference invocationImplLocal = methodEmitter.CodeBuilder.DeclareLocal(iinvocation); // TODO: Initialize iinvocation instance // with ordinary arguments and in and out arguments Expression interceptors; // if (useSelector) { // TODO: Generate code that checks the return of selector // if no interceptors is returned, should we invoke the base.Method directly? } // else { interceptors = interceptorsField.ToExpression(); } Expression typeTokenFieldExp = typeTokenField.ToExpression(); Expression methodInfoTokenExp; if (method2TokenField.ContainsKey(method)) // Token is in the cache { methodInfoTokenExp = ((FieldReference) method2TokenField[method]).ToExpression(); } else { // Not in the cache: generic method methodInfoTokenExp = new MethodTokenExpression(method.MakeGenericMethod(genericMethodArgs)); } ConstructorInfo constructor = invocationImpl.Constructors[0].ConstructorBuilder; if (isGenericInvocationClass) { constructor = TypeBuilder.GetConstructor(iinvocation, invocationImpl.Constructors[0].ConstructorBuilder); } NewInstanceExpression newInvocImpl; if (version == ConstructorVersion.WithTargetMethod) { Expression methodOnTargetTokenExp; if (method2TokenField.ContainsKey(methodOnTarget)) // Token is in the cache { methodOnTargetTokenExp = ((FieldReference) method2TokenField[methodOnTarget]).ToExpression(); } else { // Not in the cache: generic method methodOnTargetTokenExp = new MethodTokenExpression(methodOnTarget.MakeGenericMethod(genericMethodArgs)); } newInvocImpl = new NewInstanceExpression(constructor, targetRef.ToExpression(), interceptors, typeTokenFieldExp, methodOnTargetTokenExp, methodInfoTokenExp, new ReferencesToObjectArrayExpression(dereferencedArguments), SelfReference.Self.ToExpression()); } else { newInvocImpl = new NewInstanceExpression(constructor, targetRef.ToExpression(), interceptors, typeTokenFieldExp, methodInfoTokenExp, new ReferencesToObjectArrayExpression(dereferencedArguments), SelfReference.Self.ToExpression()); } methodEmitter.CodeBuilder.AddStatement(new AssignStatement(invocationImplLocal, newInvocImpl)); if (method.ContainsGenericParameters) { EmitLoadGenricMethodArguments(methodEmitter, method.MakeGenericMethod(genericMethodArgs), invocationImplLocal); } methodEmitter.CodeBuilder.AddStatement( new ExpressionStatement(new MethodInvocationExpression(invocationImplLocal, Constants.AbstractInvocationProceed))); CopyOutAndRefParameters(dereferencedArguments, invocationImplLocal, method, methodEmitter); if (method.ReturnType != typeof(void)) { // Emit code to return with cast from ReturnValue MethodInvocationExpression getRetVal = new MethodInvocationExpression(invocationImplLocal, typeof(AbstractInvocation).GetMethod("get_ReturnValue")); methodEmitter.CodeBuilder.AddStatement( new ReturnStatement(new ConvertExpression(methodEmitter.ReturnType, getRetVal))); } else { methodEmitter.CodeBuilder.AddStatement(new ReturnStatement()); } return methodEmitter; }
protected void ImplementBlankInterface( Type targetType, Type _interface, ClassEmitter emitter, FieldReference interceptorsField, ConstructorEmitter typeInitializerConstructor) { CheckNotGenericTypeDefinition(targetType, "targetType"); CheckNotGenericTypeDefinition(_interface, "_interface"); PropertyToGenerate[] propsToGenerate; EventToGenerate[] eventsToGenerate; MethodInfo[] methods = CollectMethodsAndProperties(emitter, _interface, false, out propsToGenerate, out eventsToGenerate); Dictionary<MethodInfo, NestedClassEmitter> method2Invocation = new Dictionary<MethodInfo, NestedClassEmitter>(); foreach(MethodInfo method in methods) { AddFieldToCacheMethodTokenAndStatementsToInitialize(method, typeInitializerConstructor, emitter); method2Invocation[method] = BuildInvocationNestedType(emitter, targetType, emitter.TypeBuilder, method, null, ConstructorVersion.WithoutTargetMethod); } foreach(MethodInfo method in methods) { if (method.IsSpecialName && (method.Name.StartsWith("get_") || method.Name.StartsWith("set_"))) { continue; } NestedClassEmitter nestedClass = method2Invocation[method]; MethodEmitter newProxiedMethod = CreateProxiedMethod(targetType, method, emitter, nestedClass, interceptorsField, SelfReference.Self, ConstructorVersion.WithoutTargetMethod, null); ReplicateNonInheritableAttributes(method, newProxiedMethod); } foreach(PropertyToGenerate propToGen in propsToGenerate) { if (propToGen.CanRead) { NestedClassEmitter nestedClass = method2Invocation[propToGen.GetMethod]; MethodAttributes atts = ObtainMethodAttributes(propToGen.GetMethod); MethodEmitter getEmitter = propToGen.Emitter.CreateGetMethod(atts); ImplementProxiedMethod(targetType, getEmitter, propToGen.GetMethod, emitter, nestedClass, interceptorsField, SelfReference.Self, ConstructorVersion.WithoutTargetMethod, null); ReplicateNonInheritableAttributes(propToGen.GetMethod, getEmitter); } if (propToGen.CanWrite) { NestedClassEmitter nestedClass = method2Invocation[propToGen.SetMethod]; MethodAttributes atts = ObtainMethodAttributes(propToGen.SetMethod); MethodEmitter setEmitter = propToGen.Emitter.CreateSetMethod(atts); ImplementProxiedMethod(targetType, setEmitter, propToGen.SetMethod, emitter, nestedClass, interceptorsField, SelfReference.Self, ConstructorVersion.WithoutTargetMethod, null); ReplicateNonInheritableAttributes(propToGen.SetMethod, setEmitter); } } foreach(EventToGenerate eventToGenerate in eventsToGenerate) { NestedClassEmitter add_nestedClass = method2Invocation[eventToGenerate.AddMethod]; MethodAttributes add_atts = ObtainMethodAttributes(eventToGenerate.AddMethod); MethodEmitter addEmitter = eventToGenerate.Emitter.CreateAddMethod(add_atts); ImplementProxiedMethod(targetType, addEmitter, eventToGenerate.AddMethod, emitter, add_nestedClass, interceptorsField, SelfReference.Self, ConstructorVersion.WithoutTargetMethod, null); ReplicateNonInheritableAttributes(eventToGenerate.AddMethod, addEmitter); NestedClassEmitter remove_nestedClass = method2Invocation[eventToGenerate.RemoveMethod]; MethodAttributes remove_atts = ObtainMethodAttributes(eventToGenerate.RemoveMethod); MethodEmitter removeEmitter = eventToGenerate.Emitter.CreateRemoveMethod(remove_atts); ImplementProxiedMethod(targetType, removeEmitter, eventToGenerate.RemoveMethod, emitter, remove_nestedClass, interceptorsField, SelfReference.Self, ConstructorVersion.WithoutTargetMethod, null); ReplicateNonInheritableAttributes(eventToGenerate.RemoveMethod, removeEmitter); } }
private void CreateFields(ClassEmitter emitter, Type proxyTargetType) { base.CreateFields(emitter); targetField = emitter.CreateField("__target", proxyTargetType); emitter.DefineCustomAttributeFor<XmlIgnoreAttribute>(targetField); }
public Type GenerateCode(Type proxyTargetType, Type[] interfaces, ProxyGenerationOptions options) { // make sure ProxyGenerationOptions is initialized options.Initialize(); CheckNotGenericTypeDefinition(proxyTargetType, "proxyTargetType"); CheckNotGenericTypeDefinitions(interfaces, "interfaces"); Type generatedType; ReaderWriterLock rwlock = Scope.RWLock; rwlock.AcquireReaderLock(-1); CacheKey cacheKey = new CacheKey(proxyTargetType, targetType, interfaces, options); Type cacheType = GetFromCache(cacheKey); if (cacheType != null) { rwlock.ReleaseReaderLock(); return cacheType; } rwlock.UpgradeToWriterLock(-1); try { cacheType = GetFromCache(cacheKey); if (cacheType != null) { return cacheType; } SetGenerationOptions (options); String newName = targetType.Name + "Proxy" + Guid.NewGuid().ToString("N"); // Add Interfaces that the proxy implements ArrayList interfaceList = new ArrayList(); interfaceList.Add(targetType); if (interfaces != null) { interfaceList.AddRange(interfaces); } if (!interfaceList.Contains(typeof(ISerializable))) interfaceList.Add(typeof(ISerializable)); AddMixinInterfaces(interfaceList); AddDefaultInterfaces(interfaceList); Type baseType = options.BaseTypeForInterfaceProxy; ClassEmitter emitter = BuildClassEmitter(newName, baseType, interfaceList); CreateOptionsField (emitter); emitter.DefineCustomAttribute(new XmlIncludeAttribute(targetType)); emitter.DefineCustomAttribute(new SerializableAttribute()); // Custom attributes ReplicateNonInheritableAttributes(targetType, emitter); // Fields generations FieldReference interceptorsField = emitter.CreateField("__interceptors", typeof(IInterceptor[])); targetField = emitter.CreateField("__target", proxyTargetType); emitter.DefineCustomAttributeFor(interceptorsField, new XmlIgnoreAttribute()); emitter.DefineCustomAttributeFor(targetField, new XmlIgnoreAttribute()); // Implement builtin Interfaces ImplementProxyTargetAccessor(targetType, emitter,interceptorsField); // Collect methods PropertyToGenerate[] propsToGenerate; EventToGenerate[] eventToGenerates; MethodInfo[] methods = CollectMethodsAndProperties(emitter, targetType, out propsToGenerate, out eventToGenerates); if (interfaces != null && interfaces.Length != 0) { ArrayList tmpInterfaces = new ArrayList(interfaces); foreach(Type inter in interfaces) { if (inter.IsAssignableFrom(proxyTargetType)) { PropertyToGenerate[] tempPropsToGenerate; EventToGenerate[] tempEventToGenerates; MethodInfo[] methodsTemp = CollectMethodsAndProperties(emitter, inter, out tempPropsToGenerate, out tempEventToGenerates); PropertyToGenerate[] newPropsToGenerate = new PropertyToGenerate[tempPropsToGenerate.Length + propsToGenerate.Length]; MethodInfo[] newMethods = new MethodInfo[methodsTemp.Length + methods.Length]; EventToGenerate[] newEvents = new EventToGenerate[eventToGenerates.Length + tempEventToGenerates.Length]; Array.Copy(methods, newMethods, methods.Length); Array.Copy(methodsTemp, 0, newMethods, methods.Length, methodsTemp.Length); Array.Copy(propsToGenerate, newPropsToGenerate, propsToGenerate.Length); Array.Copy(tempPropsToGenerate, 0, newPropsToGenerate, propsToGenerate.Length, tempPropsToGenerate.Length); Array.Copy(eventToGenerates, newEvents, eventToGenerates.Length); Array.Copy(tempEventToGenerates, 0, newEvents, eventToGenerates.Length, tempEventToGenerates.Length); methods = newMethods; propsToGenerate = newPropsToGenerate; eventToGenerates = newEvents; tmpInterfaces.Remove(inter); } } interfaces = (Type[]) tmpInterfaces.ToArray(typeof(Type)); } RegisterMixinMethodsAndProperties(emitter, ref methods, ref propsToGenerate, ref eventToGenerates); options.Hook.MethodsInspected(); // Constructor ConstructorEmitter typeInitializer = GenerateStaticConstructor(emitter); if (!proxyTargetType.IsInterface) { CacheMethodTokens(emitter, MethodFinder.GetAllInstanceMethods(proxyTargetType, BindingFlags.Public | BindingFlags.Instance), typeInitializer); } CreateInitializeCacheMethodBody(proxyTargetType, methods, emitter, typeInitializer); FieldReference[] mixinFields = AddMixinFields(emitter); List<FieldReference> fields = new List<FieldReference>(mixinFields); fields.Add(interceptorsField); fields.Add(targetField); GenerateConstructors(emitter, baseType, fields.ToArray()); // GenerateParameterlessConstructor(emitter, interceptorsField, baseType); // Implement interfaces if (interfaces != null && interfaces.Length != 0) { foreach(Type inter in interfaces) { ImplementBlankInterface(targetType, inter, emitter, interceptorsField, typeInitializer); } } // Create invocation types foreach(MethodInfo method in methods) { CreateInvocationForMethod(emitter, method, proxyTargetType); } // Create methods overrides Dictionary<MethodInfo, MethodEmitter> method2Emitter = new Dictionary<MethodInfo, MethodEmitter>(); foreach(MethodInfo method in methods) { if (method.IsSpecialName && (method.Name.StartsWith("get_") || method.Name.StartsWith("set_") || method.Name.StartsWith("add_") || method.Name.StartsWith("remove_")) || methodsToSkip.Contains(method)) { continue; } NestedClassEmitter nestedClass = (NestedClassEmitter) method2Invocation[method]; MethodEmitter newProxiedMethod = CreateProxiedMethod( targetType, method, emitter, nestedClass, interceptorsField, GetTargetRef(method, mixinFields, targetField), ConstructorVersion.WithTargetMethod, (MethodInfo) method2methodOnTarget[method]); ReplicateNonInheritableAttributes(method, newProxiedMethod); method2Emitter[method] = newProxiedMethod; } foreach(PropertyToGenerate propToGen in propsToGenerate) { if (propToGen.CanRead) { NestedClassEmitter nestedClass = (NestedClassEmitter) method2Invocation[propToGen.GetMethod]; MethodAttributes atts = ObtainMethodAttributes(propToGen.GetMethod); MethodEmitter getEmitter = propToGen.Emitter.CreateGetMethod(atts); ImplementProxiedMethod(targetType, getEmitter, propToGen.GetMethod, emitter, nestedClass, interceptorsField, GetTargetRef(propToGen.GetMethod, mixinFields, targetField), ConstructorVersion.WithTargetMethod, (MethodInfo) method2methodOnTarget[propToGen.GetMethod]); ReplicateNonInheritableAttributes(propToGen.GetMethod, getEmitter); // emitter.TypeBuilder.DefineMethodOverride(getEmitter.MethodBuilder, propToGen.GetMethod); } if (propToGen.CanWrite) { NestedClassEmitter nestedClass = (NestedClassEmitter) method2Invocation[propToGen.SetMethod]; MethodAttributes atts = ObtainMethodAttributes(propToGen.SetMethod); MethodEmitter setEmitter = propToGen.Emitter.CreateSetMethod(atts); ImplementProxiedMethod(targetType, setEmitter, propToGen.SetMethod, emitter, nestedClass, interceptorsField, GetTargetRef(propToGen.SetMethod, mixinFields, targetField), ConstructorVersion.WithTargetMethod, (MethodInfo) method2methodOnTarget[propToGen.SetMethod]); ReplicateNonInheritableAttributes(propToGen.SetMethod, setEmitter); // emitter.TypeBuilder.DefineMethodOverride(setEmitter.MethodBuilder, propToGen.SetMethod); } } foreach(EventToGenerate eventToGenerate in eventToGenerates) { NestedClassEmitter add_nestedClass = (NestedClassEmitter) method2Invocation[eventToGenerate.AddMethod]; MethodAttributes add_atts = ObtainMethodAttributes(eventToGenerate.AddMethod); MethodEmitter addEmitter = eventToGenerate.Emitter.CreateAddMethod(add_atts); ImplementProxiedMethod(targetType, addEmitter, eventToGenerate.AddMethod, emitter, add_nestedClass, interceptorsField, GetTargetRef(eventToGenerate.AddMethod, mixinFields, targetField), ConstructorVersion.WithTargetMethod, (MethodInfo) method2methodOnTarget[eventToGenerate.AddMethod]); ReplicateNonInheritableAttributes(eventToGenerate.AddMethod, addEmitter); NestedClassEmitter remove_nestedClass = (NestedClassEmitter) method2Invocation[eventToGenerate.RemoveMethod]; MethodAttributes remove_atts = ObtainMethodAttributes(eventToGenerate.RemoveMethod); MethodEmitter removeEmitter = eventToGenerate.Emitter.CreateRemoveMethod(remove_atts); ImplementProxiedMethod(targetType, removeEmitter, eventToGenerate.RemoveMethod, emitter, remove_nestedClass, interceptorsField, GetTargetRef(eventToGenerate.RemoveMethod, mixinFields, targetField), ConstructorVersion.WithTargetMethod, (MethodInfo) method2methodOnTarget[eventToGenerate.RemoveMethod]); ReplicateNonInheritableAttributes(eventToGenerate.RemoveMethod, removeEmitter); } ImplementGetObjectData(emitter, interceptorsField, mixinFields, interfaces); // Complete Initialize CompleteInitCacheMethod(typeInitializer.CodeBuilder); // Crosses fingers and build type generatedType = emitter.BuildType(); InitializeStaticFields (generatedType); /*foreach (MethodInfo m in TypeFinder.GetMethods(generatedType, BindingFlags.Instance | BindingFlags.Public)) { ParameterInfo[] parameters = m.GetParameters(); // Console.WriteLine(m.Name); for (int i = 0; i < parameters.Length; i++) { ParameterInfo paramInfo = parameters[i]; // Console.WriteLine("{0} {1} {2} {3}", paramInfo.Name, paramInfo.ParameterType, paramInfo.Attributes, paramInfo.Position); // Console.WriteLine("{0} {1} {2} {3}", paramInfo2.Name, paramInfo2.ParameterType, paramInfo2.Attributes, paramInfo2.Position); } } */ AddToCache(cacheKey, generatedType); } finally { rwlock.ReleaseWriterLock(); } return generatedType; }
/// <summary> /// Generates the constructor for the nested class that extends /// <see cref="AbstractInvocation"/> /// </summary> /// <param name="targetFieldType"></param> /// <param name="nested"></param> /// <param name="targetField"></param> /// <param name="version"></param> protected void CreateIInvocationConstructor( Type targetFieldType, NestedClassEmitter nested, FieldReference targetField, ConstructorVersion version) { ArgumentReference cArg0 = new ArgumentReference(targetFieldType); ArgumentReference cArg1 = new ArgumentReference(typeof(IInterceptor[])); ArgumentReference cArg2 = new ArgumentReference(typeof(Type)); ArgumentReference cArg3 = new ArgumentReference(typeof(MethodInfo)); ArgumentReference cArg4 = null; ArgumentReference cArg6 = new ArgumentReference(typeof(object)); if (version == ConstructorVersion.WithTargetMethod) { cArg4 = new ArgumentReference(typeof(MethodInfo)); } ArgumentReference cArg5 = new ArgumentReference(typeof(object[])); ConstructorEmitter constructor; if (cArg4 == null) { constructor = nested.CreateConstructor(cArg0, cArg1, cArg2, cArg3, cArg5, cArg6); } else { constructor = nested.CreateConstructor(cArg0, cArg1, cArg2, cArg3, cArg4, cArg5, cArg6); } constructor.CodeBuilder.AddStatement(new AssignStatement(targetField, cArg0.ToExpression())); if (cArg4 == null) { constructor.CodeBuilder.InvokeBaseConstructor(Constants.AbstractInvocationConstructorWithoutTargetMethod, cArg0, cArg6, cArg1, cArg2, cArg3, cArg5); } else { constructor.CodeBuilder.InvokeBaseConstructor(Constants.AbstractInvocationConstructorWithTargetMethod, cArg0, cArg6, cArg1, cArg2, cArg3, cArg4, cArg5); } constructor.CodeBuilder.AddStatement(new ReturnStatement()); }
protected void GenerateSerializationConstructor(ClassEmitter emitter, FieldReference interceptorField, bool delegateToBaseGetObjectData) { ArgumentReference arg1 = new ArgumentReference(typeof(SerializationInfo)); ArgumentReference arg2 = new ArgumentReference(typeof(StreamingContext)); ConstructorEmitter constr = emitter.CreateConstructor(arg1, arg2); constr.CodeBuilder.AddStatement( new ConstructorInvocationStatement(serializationConstructor, arg1.ToExpression(), arg2.ToExpression())); Type[] object_arg = new Type[] {typeof(String), typeof(Type)}; MethodInfo getValueMethod = typeof(SerializationInfo).GetMethod("GetValue", object_arg); MethodInvocationExpression getInterceptorInvocation = new MethodInvocationExpression(arg1, getValueMethod, new ConstReference("__interceptors").ToExpression(), new TypeTokenExpression(typeof(IInterceptor[]))); constr.CodeBuilder.AddStatement(new AssignStatement( interceptorField, new ConvertExpression(typeof(IInterceptor[]), typeof(object), getInterceptorInvocation))); constr.CodeBuilder.AddStatement(new ReturnStatement()); }
protected void CreateOptionsField(ClassEmitter emitter) { proxyGenerationOptionsField = emitter.CreateStaticField("proxyGenerationOptions", typeof(ProxyGenerationOptions)); }
protected Reference GetTargetRef(MethodInfo method, FieldReference[] mixinFields, Reference targetRef) { if (IsMixinMethod(method)) { Type interfaceType = method2MixinType[method]; int mixinIndex = ProxyGenerationOptions.MixinData.MixinInterfacesAndPositions[interfaceType]; targetRef = mixinFields[mixinIndex]; } return targetRef; }
protected MethodEmitter ImplementProxiedMethod( Type targetType, MethodEmitter methodEmitter, MethodInfo method, ClassEmitter emitter, NestedClassEmitter invocationImpl, FieldReference interceptorsField, Reference targetRef, ConstructorVersion version, MethodInfo methodOnTarget) { CheckNotGenericTypeDefinition(targetType, "targetType"); methodEmitter.CopyParametersAndReturnTypeFrom(method, emitter); TypeReference[] dereferencedArguments = IndirectReference.WrapIfByRef(methodEmitter.Arguments); Type iinvocation = invocationImpl.TypeBuilder; Trace.Assert(method.IsGenericMethod == iinvocation.IsGenericTypeDefinition); bool isGenericInvocationClass = false; Type[] genericMethodArgs = new Type[0]; if (method.IsGenericMethod) { // bind generic method arguments to invocation's type arguments genericMethodArgs = methodEmitter.MethodBuilder.GetGenericArguments(); iinvocation = iinvocation.MakeGenericType(genericMethodArgs); isGenericInvocationClass = true; } Expression typeTokenFieldExp = typeTokenField.ToExpression(); Expression methodInfoTokenExp; string tokenFieldName; if (method2TokenField.ContainsKey(method)) // Token is in the cache { FieldReference methodTokenField = method2TokenField[method]; tokenFieldName = methodTokenField.Reference.Name; methodInfoTokenExp = methodTokenField.ToExpression(); } else { // Not in the cache: generic method MethodInfo genericMethod = method.MakeGenericMethod(genericMethodArgs); // Need random suffix added to the name, so that we don't end up with duplicate field names for // methods with the same name, but different generic parameters tokenFieldName = string.Format("{0}_{1}_{2}", genericMethod.Name, genericMethodArgs.Length, Guid.NewGuid().ToString("N")); methodInfoTokenExp = new MethodTokenExpression(genericMethod); } LocalReference invocationImplLocal = methodEmitter.CodeBuilder.DeclareLocal(iinvocation); // TODO: Initialize iinvocation instance with ordinary arguments and in and out arguments Expression interceptors = interceptorsField.ToExpression(); // Create the field to store the selected interceptors for this method if an InterceptorSelector is specified FieldReference methodInterceptors = null; if (proxyGenerationOptions.Selector != null) { // If no interceptors are returned, should we invoke the base.Method directly? Looks like we should not. methodInterceptors = emitter.CreateField(string.Format("{0}_interceptors", tokenFieldName), typeof(IInterceptor[])); } ConstructorInfo constructor = invocationImpl.Constructors[0].ConstructorBuilder; if (isGenericInvocationClass) { constructor = TypeBuilder.GetConstructor(iinvocation, constructor); } NewInstanceExpression newInvocImpl; if (version == ConstructorVersion.WithTargetMethod) { Expression methodOnTargetTokenExp; if (method2TokenField.ContainsKey(methodOnTarget)) // Token is in the cache { methodOnTargetTokenExp = method2TokenField[methodOnTarget].ToExpression(); } else { // Not in the cache: generic method methodOnTargetTokenExp = new MethodTokenExpression(methodOnTarget.MakeGenericMethod(genericMethodArgs)); } if (methodInterceptors == null) { newInvocImpl = //actual contructor call new NewInstanceExpression(constructor, targetRef.ToExpression(), interceptors, typeTokenFieldExp, methodOnTargetTokenExp, methodInfoTokenExp, new ReferencesToObjectArrayExpression(dereferencedArguments), SelfReference.Self.ToExpression()); } else { MethodInvocationExpression methodInvocationExpression = new MethodInvocationExpression(proxyGenerationOptionsField, proxyGenerationOptions_Selector); methodInvocationExpression.VirtualCall = true; newInvocImpl = //actual contructor call new NewInstanceExpression(constructor, targetRef.ToExpression(), interceptors, typeTokenFieldExp, methodOnTargetTokenExp, methodInfoTokenExp, new ReferencesToObjectArrayExpression(dereferencedArguments), SelfReference.Self.ToExpression(), methodInvocationExpression, new AddressOfReferenceExpression(methodInterceptors)); } } else { if (methodInterceptors == null) { newInvocImpl = new NewInstanceExpression(constructor, targetRef.ToExpression(), interceptors, typeTokenFieldExp, methodInfoTokenExp, new ReferencesToObjectArrayExpression(dereferencedArguments), SelfReference.Self.ToExpression()); } else { MethodInvocationExpression methodInvocationExpression = new MethodInvocationExpression(proxyGenerationOptionsField, proxyGenerationOptions_Selector); methodInvocationExpression.VirtualCall = true; newInvocImpl = new NewInstanceExpression(constructor, targetRef.ToExpression(), interceptors, typeTokenFieldExp, methodInfoTokenExp, new ReferencesToObjectArrayExpression(dereferencedArguments), SelfReference.Self.ToExpression(), methodInvocationExpression, new AddressOfReferenceExpression(methodInterceptors)); } } methodEmitter.CodeBuilder.AddStatement(new AssignStatement(invocationImplLocal, newInvocImpl)); if (method.ContainsGenericParameters) { EmitLoadGenricMethodArguments(methodEmitter, method.MakeGenericMethod(genericMethodArgs), invocationImplLocal); } methodEmitter.CodeBuilder.AddStatement( new ExpressionStatement(new MethodInvocationExpression(invocationImplLocal, Constants.AbstractInvocationProceed))); CopyOutAndRefParameters(dereferencedArguments, invocationImplLocal, method, methodEmitter); if (method.ReturnType != typeof(void)) { // Emit code to return with cast from ReturnValue MethodInvocationExpression getRetVal = new MethodInvocationExpression(invocationImplLocal, typeof(AbstractInvocation).GetMethod("get_ReturnValue")); methodEmitter.CodeBuilder.AddStatement( new ReturnStatement(new ConvertExpression(methodEmitter.ReturnType, getRetVal))); } else { methodEmitter.CodeBuilder.AddStatement(new ReturnStatement()); } return methodEmitter; }
protected void ImplementBlankInterface( Type targetType, Type _interface, ClassEmitter emitter, FieldReference interceptorsField, ConstructorEmitter typeInitializerConstructor) { ImplementBlankInterface(targetType, _interface, emitter, interceptorsField, typeInitializerConstructor, false); }
private void CreateFields(ClassEmitter emitter, Type proxyTargetType) { base.CreateFields(emitter); targetField = emitter.CreateField("__target", proxyTargetType); #if SILVERLIGHT #warning XmlIncludeAttribute is in silverlight, do we want to explore this? #else emitter.DefineCustomAttributeFor<XmlIgnoreAttribute>(targetField); #endif }
public void DefineCustomAttributeFor(FieldReference field, Attribute attribute) { CustomAttributeBuilder customAttributeBuilder = CustomAttributeUtil.CreateCustomAttribute(attribute); if (customAttributeBuilder == null) return; field.Reference.SetCustomAttribute(customAttributeBuilder); }
protected void SetGenerationOptions (ProxyGenerationOptions options, ClassEmitter emitter) { if (proxyGenerationOptions != null) { throw new InvalidOperationException ("ProxyGenerationOptions can only be set once."); } proxyGenerationOptions = options; proxyGenerationOptionsField = emitter.CreateStaticField ("proxyGenerationOptions", typeof (ProxyGenerationOptions)); }
protected void CreateIInvocationInvokeOnTarget( ClassEmitter targetTypeEmitter, NestedClassEmitter nested, ParameterInfo[] parameters, FieldReference targetField, MethodInfo callbackMethod) { const MethodAttributes methodAtts = MethodAttributes.Public | MethodAttributes.Final | MethodAttributes.Virtual; MethodEmitter method = nested.CreateMethod ("InvokeMethodOnTarget", methodAtts, typeof (void)); Expression[] args = new Expression[parameters.Length]; // Idea: instead of grab parameters one by one // we should grab an array Hashtable byRefArguments = new Hashtable(); for(int i = 0; i < parameters.Length; i++) { ParameterInfo param = parameters[i]; Type paramType = param.ParameterType; if (HasGenericParameters(paramType)) { paramType = paramType.GetGenericTypeDefinition().MakeGenericType(nested.GetGenericArgumentsFor(paramType)); } else if (paramType.IsGenericParameter) { paramType = nested.GetGenericArgument(paramType.Name); } if (paramType.IsByRef) { LocalReference localReference = method.CodeBuilder.DeclareLocal(paramType.GetElementType()); method.CodeBuilder.AddStatement( new AssignStatement(localReference, new ConvertExpression(paramType.GetElementType(), new MethodInvocationExpression(SelfReference.Self, typeof(AbstractInvocation).GetMethod( "GetArgumentValue"), new LiteralIntExpression(i))))); ByRefReference byRefReference = new ByRefReference(localReference); args[i] = new ReferenceExpression(byRefReference); byRefArguments[i] = localReference; } else { args[i] = new ConvertExpression(paramType, new MethodInvocationExpression(SelfReference.Self, typeof(AbstractInvocation).GetMethod("GetArgumentValue"), new LiteralIntExpression(i))); } } MethodInvocationExpression baseMethodInvExp; if (callbackMethod.IsGenericMethod) { callbackMethod = callbackMethod.MakeGenericMethod(nested.GetGenericArgumentsFor(callbackMethod)); } baseMethodInvExp = new MethodInvocationExpression(targetField, callbackMethod, args); baseMethodInvExp.VirtualCall = true; LocalReference ret_local = null; if (callbackMethod.ReturnType != typeof(void)) { if (callbackMethod.ReturnType.IsGenericParameter) { ret_local = method.CodeBuilder.DeclareLocal(nested.GetGenericArgument(callbackMethod.ReturnType.Name)); } else if (HasGenericParameters(callbackMethod.ReturnType)) { ret_local = method.CodeBuilder.DeclareLocal( callbackMethod.ReturnType.GetGenericTypeDefinition().MakeGenericType( nested.GetGenericArgumentsFor(callbackMethod.ReturnType))); } else { ret_local = method.CodeBuilder.DeclareLocal(callbackMethod.ReturnType); } method.CodeBuilder.AddStatement(new AssignStatement(ret_local, baseMethodInvExp)); } else { method.CodeBuilder.AddStatement(new ExpressionStatement(baseMethodInvExp)); } foreach(DictionaryEntry byRefArgument in byRefArguments) { int index = (int) byRefArgument.Key; LocalReference localReference = (LocalReference) byRefArgument.Value; method.CodeBuilder.AddStatement( new ExpressionStatement( new MethodInvocationExpression(SelfReference.Self, typeof(AbstractInvocation).GetMethod("SetArgumentValue"), new LiteralIntExpression(index), new ConvertExpression(typeof(object), localReference.Type, new ReferenceExpression(localReference))) )); } if (callbackMethod.ReturnType != typeof(void)) { MethodInvocationExpression setRetVal = new MethodInvocationExpression(SelfReference.Self, typeof(AbstractInvocation).GetMethod("set_ReturnValue"), new ConvertExpression(typeof(object), ret_local.Type, ret_local.ToExpression())); method.CodeBuilder.AddStatement(new ExpressionStatement(setRetVal)); } method.CodeBuilder.AddStatement(new ReturnStatement()); }
private void CreateFields(ClassEmitter emitter, Type proxyTargetType) { base.CreateFields(emitter); targetField = emitter.CreateField("__target", proxyTargetType); #if FEATURE_SERIALIZATION emitter.DefineCustomAttributeFor<XmlIgnoreAttribute>(targetField); #endif }
protected virtual void AddAddValueInvocation(ArgumentReference serializationInfo, MethodEmitter getObjectData, FieldReference field) { getObjectData.CodeBuilder.AddStatement( new ExpressionStatement( new MethodInvocationExpression( serializationInfo, SerializationInfoMethods.AddValue_Object, new ConstReference(field.Reference.Name).ToExpression(), field.ToExpression()))); return; }
/// <summary> /// Improvement: this cache should be static. We should generate a /// type constructor instead /// </summary> protected void CreateInitializeCacheMethodBody( Type targetType, MethodInfo[] methods, ClassEmitter classEmitter, ConstructorEmitter typeInitializerConstructor) { typeTokenField = classEmitter.CreateStaticField("typeTokenCache", typeof(Type)); typeInitializerConstructor.CodeBuilder.AddStatement( new AssignStatement(typeTokenField, new TypeTokenExpression(targetType))); CacheMethodTokens(classEmitter, methods, typeInitializerConstructor); }
protected override void AddAddValueInvocation(ArgumentReference serializationInfo, MethodEmitter getObjectData, FieldReference field) { serializedFields.Add(field); base.AddAddValueInvocation(serializationInfo, getObjectData, field); }
protected void ImplementProxyTargetAccessor(Type targetType, ClassEmitter emitter, FieldReference interceptorsField) { MethodAttributes attributes = MethodAttributes.Virtual | MethodAttributes.Public; MethodEmitter DynProxyGetTarget = emitter.CreateMethod("DynProxyGetTarget", attributes, typeof (object)); DynProxyGetTarget.CodeBuilder.AddStatement( new ReturnStatement(new ConvertExpression(typeof (object), targetType, GetProxyTargetReference().ToExpression()))); MethodEmitter GetInterceptors = emitter.CreateMethod("GetInterceptors", attributes, typeof (IInterceptor[])); GetInterceptors.CodeBuilder.AddStatement( new ReturnStatement(interceptorsField) ); }
protected virtual Type Init(string typeName, out ClassEmitter emitter, Type proxyTargetType, out FieldReference interceptorsField, IEnumerable<Type> interfaces) { Type baseType = ProxyGenerationOptions.BaseTypeForInterfaceProxy; emitter = BuildClassEmitter(typeName, baseType, interfaces); CreateFields(emitter, proxyTargetType); CreateTypeAttributes(emitter); interceptorsField = emitter.GetField("__interceptors"); return baseType; }
protected virtual void ImplementGetObjectData(ClassEmitter emitter, FieldReference interceptorsField, Type[] interfaces) { if (interfaces == null) { interfaces = new Type[0]; } Type[] get_type_args = new Type[] {typeof(String), typeof(bool), typeof(bool)}; Type[] key_and_object = new Type[] {typeof(String), typeof(Object)}; MethodInfo addValueMethod = typeof(SerializationInfo).GetMethod("AddValue", key_and_object); ArgumentReference arg1 = new ArgumentReference(typeof(SerializationInfo)); ArgumentReference arg2 = new ArgumentReference(typeof(StreamingContext)); MethodEmitter getObjectData = emitter.CreateMethod("GetObjectData", typeof(void), arg1, arg2); LocalReference typeLocal = getObjectData.CodeBuilder.DeclareLocal(typeof(Type)); getObjectData.CodeBuilder.AddStatement(new AssignStatement( typeLocal, new MethodInvocationExpression(null, typeof(Type).GetMethod("GetType", get_type_args), new ConstReference( typeof(ProxyObjectReference). AssemblyQualifiedName).ToExpression(), new ConstReference(1).ToExpression(), new ConstReference(0).ToExpression()))); getObjectData.CodeBuilder.AddStatement(new ExpressionStatement( new MethodInvocationExpression( arg1, typeof(SerializationInfo).GetMethod("SetType"), typeLocal.ToExpression()))); getObjectData.CodeBuilder.AddStatement(new ExpressionStatement( new MethodInvocationExpression(arg1, addValueMethod, new ConstReference("__interceptors"). ToExpression(), interceptorsField.ToExpression()))); LocalReference interfacesLocal = getObjectData.CodeBuilder.DeclareLocal(typeof(String[])); getObjectData.CodeBuilder.AddStatement( new AssignStatement(interfacesLocal, new NewArrayExpression(interfaces.Length, typeof(String)))); for(int i = 0; i < interfaces.Length; i++) { getObjectData.CodeBuilder.AddStatement(new AssignArrayStatement( interfacesLocal, i, new ConstReference(interfaces[i].AssemblyQualifiedName).ToExpression())); } getObjectData.CodeBuilder.AddStatement(new ExpressionStatement( new MethodInvocationExpression(arg1, addValueMethod, new ConstReference("__interfaces"). ToExpression(), interfacesLocal.ToExpression()))); getObjectData.CodeBuilder.AddStatement(new ExpressionStatement( new MethodInvocationExpression(arg1, addValueMethod, new ConstReference("__baseType"). ToExpression(), new ConstReference (emitter.BaseType.AssemblyQualifiedName).ToExpression()))); getObjectData.CodeBuilder.AddStatement(new ExpressionStatement( new MethodInvocationExpression(arg1, addValueMethod, new ConstReference("__proxyGenerationOptions"). ToExpression(), proxyGenerationOptionsField.ToExpression()))); CustomizeGetObjectData(getObjectData.CodeBuilder, arg1, arg2); getObjectData.CodeBuilder.AddStatement(new ReturnStatement()); }
/// <summary> /// Generates a parameters constructor that initializes the proxy /// state with <see cref="StandardInterceptor"/> just to make it non-null. /// <para> /// This constructor is important to allow proxies to be XML serializable /// </para> /// </summary> protected void GenerateParameterlessConstructor(ClassEmitter emitter, Type baseClass, FieldReference interceptorField) { // Check if the type actually has a default constructor ConstructorInfo defaultConstructor = baseClass.GetConstructor(BindingFlags.Public | BindingFlags.Instance, null, Type.EmptyTypes, null); if (defaultConstructor == null) { defaultConstructor = baseClass.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, Type.EmptyTypes, null); if (defaultConstructor == null || defaultConstructor.IsPrivate) { return; } } ConstructorEmitter constructor = emitter.CreateConstructor(); // initialize fields with an empty interceptor constructor.CodeBuilder.AddStatement(new AssignStatement(interceptorField, new NewArrayExpression(1, typeof (IInterceptor)))); constructor.CodeBuilder.AddStatement( new AssignArrayStatement(interceptorField, 0, new NewInstanceExpression(typeof(StandardInterceptor), new Type[0]))); // Invoke base constructor constructor.CodeBuilder.InvokeBaseConstructor(defaultConstructor); constructor.CodeBuilder.AddStatement(new ReturnStatement()); }
protected MethodEmitter CreateProxiedMethod( Type targetType, MethodInfo method, ClassEmitter emitter, NestedClassEmitter invocationImpl, FieldReference interceptorsField, Reference targetRef, ConstructorVersion version, MethodInfo methodOnTarget) { CheckNotGenericTypeDefinition(targetType, "targetType"); MethodAttributes atts = ObtainMethodAttributes(method); MethodEmitter methodEmitter = emitter.CreateMethod(method.Name, atts); return ImplementProxiedMethod(targetType, methodEmitter, method, emitter, invocationImpl, interceptorsField, targetRef, version, methodOnTarget); }