Simple impl to MockRailsEngineContext.Url
[castle.git] / Tools / DynamicProxy / Castle.DynamicProxy / Builder / CodeBuilder / EasyCallable.cs
blob1d148de3aed0a6961e443d3776a92756a133240d
1 // Copyright 2004-2007 Castle Project - http://www.castleproject.org/
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 namespace Castle.DynamicProxy.Builder.CodeBuilder
17 using System;
18 using System.Reflection;
20 using Castle.DynamicProxy.Builder.CodeBuilder.Utils;
21 using Castle.DynamicProxy.Builder.CodeBuilder.SimpleAST;
23 /// <summary>
24 /// Summary description for EasyCallable.
25 /// </summary>
26 [CLSCompliant(false)]
27 public class EasyCallable : EasyNested
29 private ArgumentReference[] _args;
30 private ReturnReferenceExpression _returnType;
31 private EasyRuntimeMethod _invokeMethod;
32 private EasyConstructor _constructor;
33 private EasyMethod _callmethod;
34 private int _id;
36 public EasyCallable( AbstractEasyType type,
37 int id,
38 ReturnReferenceExpression returnType,
39 params ArgumentReference[] args ) :
40 base(type,
41 String.Format("__delegate_{0}", id),
42 typeof(MulticastDelegate),
43 new Type[] { typeof(ICallable) }, returnType, args )
45 _id = id;
46 _args = args;
47 _returnType = returnType;
49 GenerateConstructor();
50 GenerateInvoke();
51 GenerateCallableImplementation();
54 private void GenerateConstructor()
56 ArgumentReference arg1 = new ArgumentReference( typeof(object) );
57 ArgumentReference arg2 = new ArgumentReference( typeof(IntPtr) );
58 _constructor = CreateRuntimeConstructor( arg1, arg2 );
61 private void GenerateInvoke()
63 _invokeMethod = CreateRuntimeMethod( "Invoke", _returnType, _args );
66 private void GenerateCall()
68 ArgumentReference arg = new ArgumentReference( typeof(object[]) );
69 _callmethod = CreateMethod( "Call",
70 new ReturnReferenceExpression(typeof(object)), arg );
72 // LocalReference localRef = method.CodeBuilder.DeclareLocal( typeof(object) );
74 TypeReference[] dereferencedArguments = IndirectReference.WrapIfByRef(_args);
75 LocalReference[] localCopies = new LocalReference[_args.Length];
76 Expression[] invocationArguments = new Expression[_args.Length];
78 // Load arguments from the object array.
79 for (int i = 0; i < _args.Length; i++)
81 if (_args[i].Type.IsByRef)
83 localCopies[i] = _callmethod.CodeBuilder.DeclareLocal(dereferencedArguments[i].Type);
85 _callmethod.CodeBuilder.AddStatement(new AssignStatement(localCopies[i],
86 new ConvertExpression(dereferencedArguments[i].Type,
87 new LoadRefArrayElementExpression(i, arg))));
89 invocationArguments[i] = localCopies[i].ToAddressOfExpression();
91 else
93 invocationArguments[i] = new ConvertExpression(dereferencedArguments[i].Type,
94 new LoadRefArrayElementExpression(i, arg));
98 // Invoke the method.
99 MethodInvocationExpression methodInv = new MethodInvocationExpression(
100 _invokeMethod,
101 invocationArguments );
103 Expression result = null;
104 if (_returnType.Type == typeof(void))
106 _callmethod.CodeBuilder.AddStatement(new ExpressionStatement(methodInv));
107 result = NullExpression.Instance;
109 else
111 LocalReference resultLocal = _callmethod.CodeBuilder.DeclareLocal(typeof(object));
113 _callmethod.CodeBuilder.AddStatement(new AssignStatement(resultLocal,
114 new ConvertExpression(typeof(object), _returnType.Type, methodInv)));
116 result = resultLocal.ToExpression();
119 // Save ByRef arguments into the object array.
120 for (int i = 0; i < _args.Length; i++)
122 if (_args[i].Type.IsByRef)
124 _callmethod.CodeBuilder.AddStatement(new AssignArrayStatement(arg, i,
125 new ConvertExpression(typeof(object), dereferencedArguments[i].Type,
126 localCopies[i].ToExpression())));
130 // Return.
131 _callmethod.CodeBuilder.AddStatement( new ReturnStatement( result ) );
134 private void GenerateTargetProperty()
136 EasyProperty property = CreateProperty("Target", typeof(object));
137 EasyMethod getMethod = property.CreateGetMethod();
139 MethodInfo baseMethod = typeof(MulticastDelegate).GetMethod("get_Target");
141 getMethod.CodeBuilder.AddStatement(
142 new ReturnStatement( new MethodInvocationExpression(baseMethod) ) );
144 // PropertyAttributes patts = PropertyAttributes.None;
145 // PropertyBuilder pbuilder = _delegateBuilder.DefineProperty("Target", patts, typeof(Object), null);
147 // MethodAttributes atts = MethodAttributes.Public|MethodAttributes.Virtual|MethodAttributes.SpecialName;
148 // MethodBuilder methodBuilder = _delegateBuilder.DefineMethod("get_Target",
149 // atts, CallingConventions.Standard, typeof(object), new Type[0]);
151 // ILGenerator gen = methodBuilder.GetILGenerator();
153 // gen.DeclareLocal( typeof(object) );
154 // gen.Emit(OpCodes.Ldarg_0);
155 // gen.Emit(OpCodes.Call, typeof(MulticastDelegate).GetMethod("get_Target"));
156 // gen.Emit(OpCodes.Stloc_0);
157 // gen.Emit(OpCodes.Ldloc_0);
158 // gen.Emit(OpCodes.Ret);
160 // pbuilder.SetGetMethod(methodBuilder);
163 private void GenerateCallableImplementation()
165 GenerateCall();
166 GenerateTargetProperty();
169 public int ID
171 get { return _id; }
174 public EasyMethod InvokeMethod
176 get { return _invokeMethod; }
179 public EasyMethod Callmethod
181 get { return _callmethod; }
184 public ConstructorInfo Constructor
186 get { return _constructor.Builder; }