public static ProxyGeneratorResult GenerateProxy( Type typeOfProxy, IFakeCallProcessorProvider fakeCallProcessorProvider) { Guard.AgainstNull(typeOfProxy, nameof(typeOfProxy)); var invokeMethod = typeOfProxy.GetMethod("Invoke") !; if (!IsAccessibleToDynamicProxy(typeOfProxy)) { try { // This is the only way to get the proper error message. // The need for this will go away when we start really using DynamicProxy to generate delegate proxies. ProxyGenerator.CreateClassProxy(typeOfProxy); } catch (Exception ex) { return(new ProxyGeneratorResult(ex.Message)); } } var eventRaiser = new DelegateCallInterceptedEventRaiser(fakeCallProcessorProvider, invokeMethod, typeOfProxy); fakeCallProcessorProvider.EnsureInitialized(eventRaiser.Instance); return(new ProxyGeneratorResult(eventRaiser.Instance)); }
private static Delegate CreateDelegateProxy( Type typeOfProxy, MethodInfo invokeMethod, DelegateCallInterceptedEventRaiser eventRaiser) { var parameterExpressions = invokeMethod.GetParameters().Select(x => Expression.Parameter(x.ParameterType, x.Name)).ToArray(); var body = CreateBodyExpression(invokeMethod, eventRaiser, parameterExpressions); return Expression.Lambda(typeOfProxy, body, parameterExpressions).Compile(); }
private static Delegate CreateDelegateProxy( Type typeOfProxy, MethodInfo invokeMethod, DelegateCallInterceptedEventRaiser eventRaiser) { var parameterExpressions = invokeMethod.GetParameters().Select(x => Expression.Parameter(x.ParameterType, x.Name)).ToArray(); var body = CreateBodyExpression(invokeMethod, eventRaiser, parameterExpressions); return(Expression.Lambda(typeOfProxy, body, parameterExpressions).Compile()); }
// Generate a method that: // - wraps its arguments in an object array // - passes this array to eventRaiser.Raise() // - assigns the output values back to the ref/out parameters // - casts and returns the result of eventRaiser.Raise() // // For instance, for a delegate like this: // // delegate int Foo(int x, ref int y, out int z); // // We generate a method like this: // // int ProxyFoo(int x, ref int y, out int z) // { // var arguments = new[]{ (object)x, (object)y, (object)z }; // var result = (int)eventRaiser.Raise(arguments); // y = (int)arguments[1]; // z = (int)arguments[2]; // return result; // } // // Or, for a delegate with void return type: // // delegate void Foo(int x, ref int y, out int z); // // void ProxyFoo(int x, ref int y, out int z) // { // var arguments = new[]{ (object)x, (object)y, (object)z }; // eventRaiser.Raise(arguments); // y = (int)arguments[1]; // z = (int)arguments[2]; // } private static Expression CreateBodyExpression( MethodInfo delegateMethod, DelegateCallInterceptedEventRaiser eventRaiser, ParameterExpression[] parameterExpressions) { bool isVoid = delegateMethod.ReturnType == typeof(void); // Local variables of the generated method var arguments = Expression.Variable(typeof(object[]), "arguments"); var result = isVoid ? null : Expression.Variable(delegateMethod.ReturnType, "result"); var bodyExpressions = new List <Expression>(); bodyExpressions.Add(Expression.Assign(arguments, WrapParametersInObjectArray(parameterExpressions))); Expression call = Expression.Call( Expression.Constant(eventRaiser), DelegateCallInterceptedEventRaiser.RaiseMethod, arguments); if (!isVoid) { // If the return type is non void, cast the result of eventRaiser.Raise() // to the real return type and assign to the result variable call = Expression.Assign(result, Expression.Convert(call, delegateMethod.ReturnType)); } bodyExpressions.Add(call); // After the call, copy the values back to the ref/out parameters for (int index = 0; index < parameterExpressions.Length; index++) { var parameter = parameterExpressions[index]; if (parameter.IsByRef) { var assignment = AssignParameterFromArrayElement(arguments, index, parameter); bodyExpressions.Add(assignment); } } // Return the result if the return type is non-void if (!isVoid) { bodyExpressions.Add(result); } var variables = isVoid ? new[] { arguments } : new[] { arguments, result }; return(Expression.Block(variables, bodyExpressions)); }
public static ProxyGeneratorResult GenerateProxy( Type typeOfProxy, IFakeCallProcessorProvider fakeCallProcessorProvider) { Guard.AgainstNull(typeOfProxy, nameof(typeOfProxy)); if (!CanGenerateProxy(typeOfProxy, out string reasonCannotGenerate)) { return(new ProxyGeneratorResult(reasonCannotGenerate)); } var invokeMethod = typeOfProxy.GetMethod("Invoke"); var eventRaiser = new DelegateCallInterceptedEventRaiser(fakeCallProcessorProvider, invokeMethod, typeOfProxy); fakeCallProcessorProvider.EnsureInitialized(eventRaiser.Instance); return(new ProxyGeneratorResult(eventRaiser.Instance)); }
private static Expression CreateBodyExpression( MethodInfo delegateMethod, DelegateCallInterceptedEventRaiser eventRaiser, IEnumerable<Expression> parameterExpressions) { var parameterExpressionsCastToObject = parameterExpressions.Select(x => Expression.Convert(x, typeof(object))).Cast<Expression>().ToArray(); Expression body = Expression.Call( Expression.Constant(eventRaiser), DelegateCallInterceptedEventRaiser.RaiseMethod, new Expression[] { Expression.NewArrayInit(typeof(object), parameterExpressionsCastToObject) }); if (!delegateMethod.ReturnType.Equals(typeof(void))) { body = Expression.Convert(body, delegateMethod.ReturnType); } return body; }
private static Expression CreateBodyExpression( MethodInfo delegateMethod, DelegateCallInterceptedEventRaiser eventRaiser, Expression[] parameterExpressions) { var parameterExpressionsCastToObject = parameterExpressions.Select(x => Expression.Convert(x, typeof(object))).Cast <Expression>().ToArray(); Expression body = Expression.Call( Expression.Constant(eventRaiser), DelegateCallInterceptedEventRaiser.RaiseMethod, new Expression[] { Expression.NewArrayInit(typeof(object), parameterExpressionsCastToObject) }); if (!delegateMethod.ReturnType.Equals(typeof(void))) { body = Expression.Convert(body, delegateMethod.ReturnType); } return(body); }
public virtual ProxyGeneratorResult GenerateProxy( Type typeOfProxy, IEnumerable<Type> additionalInterfacesToImplement, IEnumerable<object> argumentsForConstructor, IFakeCallProcessorProvider fakeCallProcessorProvider) { Guard.AgainstNull(typeOfProxy, nameof(typeOfProxy)); if (!typeof(Delegate).IsAssignableFrom(typeOfProxy)) { return new ProxyGeneratorResult("The delegate proxy generator can only create proxies for delegate types."); } var invokeMethod = typeOfProxy.GetMethod("Invoke"); var eventRaiser = new DelegateCallInterceptedEventRaiser(fakeCallProcessorProvider, invokeMethod, typeOfProxy); fakeCallProcessorProvider.EnsureInitialized(eventRaiser.Instance); return new ProxyGeneratorResult(eventRaiser.Instance); }
public virtual ProxyGeneratorResult GenerateProxy( Type typeOfProxy, IEnumerable <Type> additionalInterfacesToImplement, IEnumerable <object> argumentsForConstructor, IFakeCallProcessorProvider fakeCallProcessorProvider) { Guard.AgainstNull(typeOfProxy, nameof(typeOfProxy)); if (!typeof(Delegate).IsAssignableFrom(typeOfProxy)) { return(new ProxyGeneratorResult("The delegate proxy generator can only create proxies for delegate types.")); } var invokeMethod = typeOfProxy.GetMethod("Invoke"); var eventRaiser = new DelegateCallInterceptedEventRaiser(fakeCallProcessorProvider, invokeMethod, typeOfProxy); fakeCallProcessorProvider.EnsureInitialized(eventRaiser.Instance); return(new ProxyGeneratorResult(eventRaiser.Instance)); }
public virtual ProxyGeneratorResult GenerateProxy(Type typeOfProxy, IEnumerable<Type> additionalInterfacesToImplement, IEnumerable<object> argumentsForConstructor) { if (!typeof (Delegate).IsAssignableFrom(typeOfProxy)) { return new ProxyGeneratorResult("The delegate proxy generator can only create proxies for delegate types."); } var invokeMethod = typeOfProxy.GetMethod("Invoke"); var eventRaiser = new DelegateCallInterceptedEventRaiser(); var proxy = CreateDelegateProxy(typeOfProxy, invokeMethod, eventRaiser); eventRaiser.Method = invokeMethod; eventRaiser.Instance = proxy; return new ProxyGeneratorResult(proxy, eventRaiser); }
public virtual ProxyGeneratorResult GenerateProxy( Type typeOfProxy, IEnumerable <Type> additionalInterfacesToImplement, IEnumerable <object> argumentsForConstructor) { if (!typeof(Delegate).IsAssignableFrom(typeOfProxy)) { return (new ProxyGeneratorResult("The delegate proxy generator can only create proxies for delegate types.")); } var invokeMethod = typeOfProxy.GetMethod("Invoke"); var eventRaiser = new DelegateCallInterceptedEventRaiser(); var proxy = CreateDelegateProxy(typeOfProxy, invokeMethod, eventRaiser); eventRaiser.Method = invokeMethod; eventRaiser.Instance = proxy; return(new ProxyGeneratorResult(proxy, eventRaiser)); }
public virtual ProxyGeneratorResult GenerateProxy( Type typeOfProxy, IEnumerable <Type> additionalInterfacesToImplement, IEnumerable <object> argumentsForConstructor, IEnumerable <Expression <Func <Attribute> > > attributes, IFakeCallProcessorProvider fakeCallProcessorProvider) { Guard.AgainstNull(typeOfProxy, nameof(typeOfProxy)); if (!this.CanGenerateProxy(typeOfProxy, out string reasonCannotGenerate)) { return(new ProxyGeneratorResult(reasonCannotGenerate)); } var invokeMethod = typeOfProxy.GetMethod("Invoke"); var eventRaiser = new DelegateCallInterceptedEventRaiser(fakeCallProcessorProvider, invokeMethod, typeOfProxy); fakeCallProcessorProvider.EnsureInitialized(eventRaiser.Instance); return(new ProxyGeneratorResult(eventRaiser.Instance)); }
// Generate a method that: // - wraps its arguments in an object array // - passes this array to eventRaiser.Raise() // - assigns the output values back to the ref/out parameters // - casts and returns the result of eventRaiser.Raise() // // For instance, for a delegate like this: // // delegate int Foo(int x, ref int y, out int z); // // We generate a method like this: // // int ProxyFoo(int x, ref int y, out int z) // { // var arguments = new[]{ (object)x, (object)y, (object)z }; // var result = (int)eventRaiser.Raise(arguments); // y = (int)arguments[1]; // z = (int)arguments[2]; // return result; // } // // Or, for a delegate with void return type: // // delegate void Foo(int x, ref int y, out int z); // // void ProxyFoo(int x, ref int y, out int z) // { // var arguments = new[]{ (object)x, (object)y, (object)z }; // eventRaiser.Raise(arguments); // y = (int)arguments[1]; // z = (int)arguments[2]; // } private static Expression CreateBodyExpression( MethodInfo delegateMethod, DelegateCallInterceptedEventRaiser eventRaiser, ParameterExpression[] parameterExpressions) { bool isVoid = delegateMethod.ReturnType == typeof(void); // Local variables of the generated method var arguments = Expression.Variable(typeof(object[]), "arguments"); var result = isVoid ? null : Expression.Variable(delegateMethod.ReturnType, "result"); var bodyExpressions = new List<Expression>(); bodyExpressions.Add(Expression.Assign(arguments, WrapParametersInObjectArray(parameterExpressions))); Expression call = Expression.Call( Expression.Constant(eventRaiser), DelegateCallInterceptedEventRaiser.RaiseMethod, arguments); if (!isVoid) { // If the return type is non void, cast the result of eventRaiser.Raise() // to the real return type and assign to the result variable call = Expression.Assign(result, Expression.Convert(call, delegateMethod.ReturnType)); } bodyExpressions.Add(call); // After the call, copy the values back to the ref/out parameters for (int index = 0; index < parameterExpressions.Length; index++) { var parameter = parameterExpressions[index]; if (parameter.IsByRef) { var assignment = AssignParameterFromArrayElement(arguments, index, parameter); bodyExpressions.Add(assignment); } } // Return the result if the return type is non-void if (!isVoid) { bodyExpressions.Add(result); } var variables = isVoid ? new[] { arguments } : new[] { arguments, result }; return Expression.Block(variables, bodyExpressions); }