public void UsingClassEmitterForInterfaces() { ClassEmitter emitter = new ClassEmitter( generator.ProxyBuilder.ModuleScope, "IFoo", null, Type.EmptyTypes, TypeAttributes.Interface | TypeAttributes.Abstract | TypeAttributes.Public, false ); emitter.CreateMethod( "MyMethod", MethodAttributes.Public | MethodAttributes.Abstract | MethodAttributes.Virtual, typeof(void), Type.EmptyTypes ); Type t = emitter.BuildType(); Assert.IsTrue(t.IsInterface); MethodInfo method = t.GetMethod("MyMethod"); Assert.IsNotNull(method); }
public virtual void Generate(ClassEmitter @class) { foreach (var method in methods) { if (!method.Standalone) { continue; } ImplementMethod(method, @class, @class.CreateMethod); } foreach (var property in properties) { ImplementProperty(@class, property); } foreach (var @event in events) { ImplementEvent(@class, @event); } }
private Type GetInvocationType(MetaMethod method, ClassEmitter emitter, ProxyGenerationOptions options) { var scope = emitter.ModuleScope; Type[] invocationInterfaces; if (canChangeTarget) { invocationInterfaces = new[] { typeof(IInvocation), typeof(IChangeProxyTarget) }; } else { invocationInterfaces = new[] { typeof(IInvocation) }; } var key = new CacheKey(method.Method, CompositionInvocationTypeGenerator.BaseType, invocationInterfaces, null); // no locking required as we're already within a lock var invocation = scope.GetFromCache(key); if (invocation != null) { return(invocation); } invocation = new CompositionInvocationTypeGenerator(method.Method.DeclaringType, method, method.Method, canChangeTarget, null) .Generate(emitter, options, namingScope) .BuildType(); scope.RegisterInCache(key, invocation); return(invocation); }
protected override void CustomizeGetObjectData( CodeBuilder codebuilder, ArgumentReference serializationInfo, ArgumentReference streamingContext, ClassEmitter emitter ) { codebuilder.AddStatement( new MethodInvocationExpression( serializationInfo, SerializationInfoMethods.AddValue_Bool, new LiteralStringExpression("__delegateToBase"), new LiteralBoolExpression(delegateToBaseGetObjectData) ) ); if (delegateToBaseGetObjectData == false) { EmitCustomGetObjectData(codebuilder, serializationInfo); return; } EmitCallToBaseGetObjectData(codebuilder, serializationInfo, streamingContext); }
public void InstanceMethodArguments() { ClassEmitter emitter = new ClassEmitter( generator.ProxyBuilder.ModuleScope, "Foo", typeof(List <object>), Type.EmptyTypes ); MethodEmitter methodEmitter = emitter.CreateMethod( "InstanceMethod", MethodAttributes.Public, typeof(string), typeof(string) ); methodEmitter.CodeBuilder.AddStatement(new ReturnStatement(methodEmitter.Arguments[0])); Type t = emitter.BuildType(); object instance = Activator.CreateInstance(t); Assert.AreEqual( "six", t.GetMethod("InstanceMethod").Invoke(instance, new object[] { "six" }) ); }
protected override MethodGenerator GetMethodGenerator(MetaMethod method, ClassEmitter @class, OverrideMethodDelegate overrideMethod) { if (method.Ignore) { return(null); } var methodIsDirectlyAccessible = IsDirectlyAccessible(method); if (!method.Proxyable) { if (methodIsDirectlyAccessible) { return(new ForwardingMethodGenerator(method, overrideMethod, (c, m) => c.GetField("__target"))); } else { return(IndirectlyCalledMethodGenerator(method, @class, overrideMethod, skipInterceptors: true)); } } if (!methodIsDirectlyAccessible) { return(IndirectlyCalledMethodGenerator(method, @class, overrideMethod)); } var invocation = GetInvocationType(method, @class); return(new MethodWithInvocationGenerator(method, @class.GetField("__interceptors"), invocation, (c, m) => c.GetField("__target"), overrideMethod, null)); }
protected void GenerateConstructor(ClassEmitter emitter, ConstructorInfo baseConstructor, params FieldReference[] fields) { ArgumentReference[] args; ParameterInfo[] baseConstructorParams = null; if (baseConstructor != null) { baseConstructorParams = baseConstructor.GetParameters(); } if (baseConstructorParams != null && baseConstructorParams.Length != 0) { args = new ArgumentReference[fields.Length + baseConstructorParams.Length]; var offset = fields.Length; for (var i = offset; i < offset + baseConstructorParams.Length; i++) { var paramInfo = baseConstructorParams[i - offset]; args[i] = new ArgumentReference(paramInfo.ParameterType); } } else { args = new ArgumentReference[fields.Length]; } for (var i = 0; i < fields.Length; i++) { args[i] = new ArgumentReference(fields[i].Reference.FieldType); } var constructor = emitter.CreateConstructor(args); if (baseConstructorParams != null && baseConstructorParams.Length != 0) { var last = baseConstructorParams.Last(); if (last.ParameterType.GetTypeInfo().IsArray&& last.IsDefined(typeof(ParamArrayAttribute))) { var parameter = constructor.ConstructorBuilder.DefineParameter(args.Length, ParameterAttributes.None, last.Name); var builder = AttributeUtil.CreateBuilder <ParamArrayAttribute>(); parameter.SetCustomAttribute(builder); } } for (var i = 0; i < fields.Length; i++) { constructor.CodeBuilder.AddStatement(new AssignStatement(fields[i], args[i].ToExpression())); } // Invoke base constructor if (baseConstructor != null) { Debug.Assert(baseConstructorParams != null); var slice = new ArgumentReference[baseConstructorParams.Length]; Array.Copy(args, fields.Length, slice, 0, baseConstructorParams.Length); constructor.CodeBuilder.InvokeBaseConstructor(baseConstructor, slice); } else { constructor.CodeBuilder.InvokeBaseConstructor(); } constructor.CodeBuilder.AddStatement(new ReturnStatement()); }
protected virtual void CreateFields(ClassEmitter emitter) { CreateOptionsField(emitter); CreateSelectorField(emitter); CreateInterceptorsField(emitter); }
protected new void CreateInterceptorsField(ClassEmitter emitter) => emitter.CreateField("__interceptors", Options.InterceptorType.MakeArrayType());
private Reference GetTarget(ClassEmitter @class, MethodInfo method) { return(new AsTypeReference(@class.GetField("__target"), method.DeclaringType)); }
protected override void CustomizeGetObjectData(CodeBuilder codebuilder, ArgumentReference serializationInfo, ArgumentReference streamingContext, ClassEmitter emitter) { var targetField = emitter.GetField("__target"); codebuilder.AddStatement( new MethodInvocationExpression( serializationInfo, SerializationInfoMethods.AddValue_Object, new LiteralStringExpression("__targetFieldType"), new LiteralStringExpression(targetField.Reference.FieldType.AssemblyQualifiedName))); codebuilder.AddStatement( new MethodInvocationExpression( serializationInfo, SerializationInfoMethods.AddValue_Object, new LiteralStringExpression("__theInterface"), new LiteralStringExpression(targetType.AssemblyQualifiedName))); }
protected void ImplementGetObjectData(ClassEmitter emitter) { var getObjectData = emitter.CreateMethod( "GetObjectData", typeof(void), new[] { typeof(SerializationInfo), typeof(StreamingContext) } ); var info = getObjectData.Arguments[0]; var typeLocal = getObjectData.CodeBuilder.DeclareLocal(typeof(Type)); getObjectData.CodeBuilder.AddStatement( new AssignStatement( typeLocal, new MethodInvocationExpression( null, TypeMethods.StaticGetType, new LiteralStringExpression( typeof(ProxyObjectReference).AssemblyQualifiedName ), new LiteralBoolExpression(true), new LiteralBoolExpression(false) ) ) ); getObjectData.CodeBuilder.AddStatement( new MethodInvocationExpression(info, SerializationInfoMethods.SetType, typeLocal) ); foreach (var field in emitter.GetAllFields()) { if (field.Reference.IsStatic) { continue; } if (field.Reference.IsNotSerialized) { continue; } AddAddValueInvocation(info, getObjectData, field); } var interfacesLocal = getObjectData.CodeBuilder.DeclareLocal(typeof(string[])); getObjectData.CodeBuilder.AddStatement( new AssignStatement( interfacesLocal, new NewArrayExpression(interfaces.Length, typeof(string)) ) ); for (var i = 0; i < interfaces.Length; i++) { getObjectData.CodeBuilder.AddStatement( new AssignArrayStatement( interfacesLocal, i, new LiteralStringExpression(interfaces[i].AssemblyQualifiedName) ) ); } getObjectData.CodeBuilder.AddStatement( new MethodInvocationExpression( info, SerializationInfoMethods.AddValue_Object, new LiteralStringExpression("__interfaces"), interfacesLocal ) ); getObjectData.CodeBuilder.AddStatement( new MethodInvocationExpression( info, SerializationInfoMethods.AddValue_Object, new LiteralStringExpression("__baseType"), new LiteralStringExpression(emitter.BaseType.AssemblyQualifiedName) ) ); getObjectData.CodeBuilder.AddStatement( new MethodInvocationExpression( info, SerializationInfoMethods.AddValue_Object, new LiteralStringExpression("__proxyGenerationOptions"), emitter.GetField("proxyGenerationOptions") ) ); getObjectData.CodeBuilder.AddStatement( new MethodInvocationExpression( info, SerializationInfoMethods.AddValue_Object, new LiteralStringExpression("__proxyTypeId"), new LiteralStringExpression(proxyTypeId) ) ); CustomizeGetObjectData( getObjectData.CodeBuilder, info, getObjectData.Arguments[1], emitter ); getObjectData.CodeBuilder.AddStatement(new ReturnStatement()); }
protected override Expression GetTargetReferenceExpression(ClassEmitter emitter) { return(emitter.GetField("__target").ToExpression()); }
protected override void CreateFields(ClassEmitter emitter) { base.CreateFields(emitter); CreateTargetField(emitter); }
private FieldReference BuildTargetField(ClassEmitter @class, Type type) { var name = "__mixin_" + type.FullName.Replace(".", "_"); return(@class.CreateField(namingScope.GetUniqueName(name), type)); }
protected abstract void CustomizeGetObjectData( CodeBuilder builder, ArgumentReference serializationInfo, ArgumentReference streamingContext, ClassEmitter emitter );
public virtual void Generate(ClassEmitter @class) { ImplementGetObjectData(@class); }
protected void GenerateConstructor(ClassEmitter emitter, ConstructorInfo baseConstructor, params FieldReference[] fields) { ArgumentReference[] args; ParameterInfo[] baseConstructorParams = null; if (baseConstructor != null) { baseConstructorParams = baseConstructor.GetParameters(); } if (baseConstructorParams != null && baseConstructorParams.Length != 0) { args = new ArgumentReference[fields.Length + baseConstructorParams.Length]; var offset = fields.Length; for (var i = offset; i < offset + baseConstructorParams.Length; i++) { var paramInfo = baseConstructorParams[i - offset]; args[i] = new ArgumentReference(paramInfo.ParameterType); } } else { args = new ArgumentReference[fields.Length]; } for (var i = 0; i < fields.Length; i++) { args[i] = new ArgumentReference(fields[i].Reference.FieldType); } var constructor = emitter.CreateConstructor(args); if (baseConstructorParams != null && baseConstructorParams.Length != 0) { var offset = 1 + fields.Length; for (int i = 0, n = baseConstructorParams.Length; i < n; ++i) { var parameterBuilder = constructor.ConstructorBuilder.DefineParameter(offset + i, baseConstructorParams[i].Attributes, baseConstructorParams[i].Name); foreach (var attribute in baseConstructorParams[i].GetNonInheritableAttributes()) { parameterBuilder.SetCustomAttribute(attribute.Builder); } } } for (var i = 0; i < fields.Length; i++) { constructor.CodeBuilder.AddStatement(new AssignStatement(fields[i], args[i].ToExpression())); } // Invoke base constructor if (baseConstructor != null) { Debug.Assert(baseConstructorParams != null); var slice = new ArgumentReference[baseConstructorParams.Length]; Array.Copy(args, fields.Length, slice, 0, baseConstructorParams.Length); constructor.CodeBuilder.InvokeBaseConstructor(baseConstructor, slice); } else { constructor.CodeBuilder.InvokeBaseConstructor(); } constructor.CodeBuilder.AddStatement(new ReturnStatement()); }
protected override MethodEmitter BuildProxiedMethodBody(MethodEmitter emitter, ClassEmitter @class, INamingScope namingScope) { var targetReference = getTargetReference(@class, MethodToOverride); var arguments = ArgumentsUtil.ConvertToArgumentReferenceExpression(MethodToOverride.GetParameters()); emitter.CodeBuilder.AddStatement(new ReturnStatement( new MethodInvocationExpression( targetReference, MethodToOverride, arguments) { VirtualCall = true })); return(emitter); }
protected override MethodEmitter BuildProxiedMethodBody(MethodEmitter emitter, ClassEmitter @class, INamingScope namingScope) { var invocationType = invocation; Trace.Assert(MethodToOverride.IsGenericMethod == invocationType.IsGenericTypeDefinition); var genericArguments = Type.EmptyTypes; var constructor = invocation.GetConstructors()[0]; Expression proxiedMethodTokenExpression; if (MethodToOverride.IsGenericMethod) { // bind generic method arguments to invocation's type arguments genericArguments = emitter.MethodBuilder.GetGenericArguments(); invocationType = invocationType.MakeGenericType(genericArguments); constructor = TypeBuilder.GetConstructor(invocationType, constructor); // Not in the cache: generic method proxiedMethodTokenExpression = new MethodTokenExpression(MethodToOverride.MakeGenericMethod(genericArguments)); } else { var proxiedMethodToken = @class.CreateStaticField(namingScope.GetUniqueName("token_" + MethodToOverride.Name), typeof(MethodInfo)); @class.ClassConstructor.CodeBuilder.AddStatement(new AssignStatement(proxiedMethodToken, new MethodTokenExpression(MethodToOverride))); proxiedMethodTokenExpression = proxiedMethodToken.ToExpression(); } var methodInterceptors = SetMethodInterceptors(@class, namingScope, emitter, proxiedMethodTokenExpression); var dereferencedArguments = IndirectReference.WrapIfByRef(emitter.Arguments); var hasByRefArguments = HasByRefArguments(emitter.Arguments); var arguments = GetCtorArguments(@class, proxiedMethodTokenExpression, dereferencedArguments, methodInterceptors); var ctorArguments = ModifyArguments(@class, arguments); var invocationLocal = emitter.CodeBuilder.DeclareLocal(invocationType); emitter.CodeBuilder.AddStatement(new AssignStatement(invocationLocal, new NewInstanceExpression(constructor, ctorArguments))); if (MethodToOverride.ContainsGenericParameters) { EmitLoadGenricMethodArguments(emitter, MethodToOverride.MakeGenericMethod(genericArguments), invocationLocal); } if (hasByRefArguments) { emitter.CodeBuilder.AddStatement(new TryStatement()); } var proceed = new ExpressionStatement(new MethodInvocationExpression(invocationLocal, InvocationMethods.Proceed)); emitter.CodeBuilder.AddStatement(proceed); if (hasByRefArguments) { emitter.CodeBuilder.AddStatement(new FinallyStatement()); } GeneratorUtil.CopyOutAndRefParameters(dereferencedArguments, invocationLocal, MethodToOverride, emitter); if (hasByRefArguments) { emitter.CodeBuilder.AddStatement(new EndExceptionBlockStatement()); } if (MethodToOverride.ReturnType != typeof(void)) { var getRetVal = new MethodInvocationExpression(invocationLocal, InvocationMethods.GetReturnValue); // Emit code to ensure a value type return type is not null, otherwise the cast will cause a null-deref if (emitter.ReturnType.IsValueType && !emitter.ReturnType.IsNullableType()) { LocalReference returnValue = emitter.CodeBuilder.DeclareLocal(typeof(object)); emitter.CodeBuilder.AddStatement(new AssignStatement(returnValue, getRetVal)); emitter.CodeBuilder.AddExpression(new IfNullExpression(returnValue, new ThrowStatement(typeof(InvalidOperationException), "Interceptors failed to set a return value, or swallowed the exception thrown by the target"))); } // Emit code to return with cast from ReturnValue emitter.CodeBuilder.AddStatement(new ReturnStatement(new ConvertExpression(emitter.ReturnType, getRetVal))); } else { emitter.CodeBuilder.AddStatement(new ReturnStatement()); } return(emitter); }
protected override MethodEmitter BuildProxiedMethodBody(MethodEmitter emitter, ClassEmitter @class, ProxyGenerationOptions options, INamingScope namingScope) { var targetReference = getTargetReference(@class, MethodToOverride); emitter.CodeBuilder.AddStatement( new ExpressionStatement( new IfNullExpression(targetReference, IfNull(emitter.ReturnType), IfNotNull(targetReference)))); return(emitter); }
public Expression[] GetConstructorInvocationArguments(Expression[] arguments, ClassEmitter proxy) { return(arguments); }
private Expression GetTargetExpression(ClassEmitter @class, MethodInfo method) { return(GetTarget(@class, method).ToExpression()); }
protected void GenerateConstructor(ClassEmitter emitter, ConstructorInfo baseConstructor, params FieldReference[] fields) { GenerateConstructor(emitter, baseConstructor, ProxyConstructorImplementation.CallBase, fields); }
protected override MethodEmitter BuildProxiedMethodBody(MethodEmitter emitter, ClassEmitter @class, ProxyGenerationOptions options, INamingScope namingScope) { var invocationType = invocation; Trace.Assert(MethodToOverride.IsGenericMethod == invocationType.IsGenericTypeDefinition()); var genericArguments = TypeExtender.EmptyTypes; var constructor = invocation.GetConstructors()[0]; Expression proxiedMethodTokenExpression; if (MethodToOverride.IsGenericMethod) { // bind generic method arguments to invocation's type arguments genericArguments = emitter.MethodBuilder.GetGenericArguments(); invocationType = invocationType.MakeGenericType(genericArguments); constructor = TypeBuilder.GetConstructor(invocationType, constructor); // Not in the cache: generic method proxiedMethodTokenExpression = new MethodTokenExpression(MethodToOverride.MakeGenericMethod(genericArguments)); } else { var proxiedMethodToken = @class.CreateStaticField(namingScope.GetUniqueName("token_" + MethodToOverride.Name), typeof(IMethodInfo)); @class.ClassConstructor.CodeBuilder.AddStatement(new AssignStatement(proxiedMethodToken, new MethodTokenExpression(MethodToOverride))); proxiedMethodTokenExpression = proxiedMethodToken.ToExpression(); } var dereferencedArguments = IndirectReference.WrapIfByRef(emitter.Arguments); var hasByRefArguments = HasByRefArguments(emitter.Arguments); var arguments = GetCtorArguments(@class, namingScope, proxiedMethodTokenExpression, dereferencedArguments); var ctorArguments = ModifyArguments(@class, arguments); var invocationLocal = emitter.CodeBuilder.DeclareLocal(invocationType); emitter.CodeBuilder.AddStatement(new AssignStatement(invocationLocal, new NewInstanceExpression(constructor, ctorArguments))); if (MethodToOverride.ContainsGenericParameters) { EmitLoadGenricMethodArguments(emitter, MethodToOverride.MakeGenericMethod(genericArguments), invocationLocal); } if (hasByRefArguments) { emitter.CodeBuilder.AddStatement(new TryStatement()); } var proceed = new ExpressionStatement(new MethodInvocationExpression(invocationLocal, InvocationMethods.Proceed)); emitter.CodeBuilder.AddStatement(proceed); if (hasByRefArguments) { emitter.CodeBuilder.AddStatement(new FinallyStatement()); } GeneratorUtil.CopyOutAndRefParameters(dereferencedArguments, invocationLocal, MethodToOverride, emitter); if (hasByRefArguments) { emitter.CodeBuilder.AddStatement(new EndExceptionBlockStatement()); } if (MethodToOverride.ReturnType != typeof(void)) { var getRetVal = new MethodInvocationExpression(invocationLocal, InvocationMethods.GetReturnValue); emitter.CodeBuilder.AddStatement(new ReturnStatement(new ConvertExpression(emitter.ReturnType, getRetVal))); } else { emitter.CodeBuilder.AddStatement(new ReturnStatement()); } return(emitter); }
protected override MethodEmitter BuildProxiedMethodBody(MethodEmitter emitter, ClassEmitter @class, ProxyGenerationOptions options, INamingScope namingScope) { InitOutParameters(emitter, MethodToOverride.GetParameters()); if (emitter.ReturnType == typeof(void)) { emitter.CodeBuilder.AddStatement(new ReturnStatement()); } else { emitter.CodeBuilder.AddStatement(new ReturnStatement(new DefaultValueExpression(emitter.ReturnType))); } return(emitter); }
protected FieldReference CreateOptionsField(ClassEmitter emitter) { return(emitter.CreateStaticField("proxyGenerationOptions", typeof(ProxyGenerationOptions))); }
protected override Reference GetTargetReference(ClassEmitter emitter) { return(emitter.GetField("__target")); }
protected ConstructorEmitter GenerateStaticConstructor(ClassEmitter emitter) { return(emitter.CreateTypeConstructor()); }
protected abstract Expression GetTargetReferenceExpression(ClassEmitter emitter);