2009-07-11 Michael Barker <mike@middlesoft.co.uk>
[mono.git] / mcs / class / dlr / Runtime / Microsoft.Dynamic / DispatchArgBuilder.cs
1 /* ****************************************************************************
2  *
3  * Copyright (c) Microsoft Corporation. 
4  *
5  * This source code is subject to terms and conditions of the Microsoft Public License. A 
6  * copy of the license can be found in the License.html file at the root of this distribution. If 
7  * you cannot locate the  Microsoft Public License, please send an email to 
8  * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
9  * by the terms of the Microsoft Public License.
10  *
11  * You must not remove this notice, or any other, from this software.
12  *
13  *
14  * ***************************************************************************/
15 using System; using Microsoft;
16
17
18 #if !SILVERLIGHT // ComObject
19
20 using System.Collections.Generic;
21 #if CODEPLEX_40
22 using System.Linq.Expressions;
23 #else
24 using Microsoft.Linq.Expressions;
25 #endif
26 using System.Runtime.InteropServices;
27 using System.Diagnostics;
28 #if CODEPLEX_40
29 using System.Dynamic.Utils;
30 #else
31 using Microsoft.Scripting.Utils;
32 #endif
33
34 #if CODEPLEX_40
35 namespace System.Dynamic {
36 #else
37 namespace Microsoft.Scripting {
38 #endif
39
40     internal class DispatchArgBuilder : SimpleArgBuilder {
41         private readonly bool _isWrapper;
42
43         internal DispatchArgBuilder(Type parameterType)
44             : base(parameterType) {
45
46             _isWrapper = parameterType == typeof(DispatchWrapper);
47         }
48
49         internal override Expression Marshal(Expression parameter) {
50             parameter = base.Marshal(parameter);
51
52             // parameter.WrappedObject
53             if (_isWrapper) {
54                 parameter = Expression.Property(
55                     Helpers.Convert(parameter, typeof(DispatchWrapper)),
56                     typeof(DispatchWrapper).GetProperty("WrappedObject")
57                 );
58             };
59
60             return Helpers.Convert(parameter, typeof(object));
61         }
62
63         internal override Expression MarshalToRef(Expression parameter) {
64             parameter = Marshal(parameter);
65
66             // parameter == null ? IntPtr.Zero : Marshal.GetIDispatchForObject(parameter);
67             return Expression.Condition(
68                 Expression.Equal(parameter, Expression.Constant(null)),
69                 Expression.Constant(IntPtr.Zero),
70                 Expression.Call(
71                     typeof(Marshal).GetMethod("GetIDispatchForObject"),
72                     parameter
73                 )
74             );
75         }
76
77         internal override Expression UnmarshalFromRef(Expression value) {
78             // value == IntPtr.Zero ? null : Marshal.GetObjectForIUnknown(value);
79             Expression unmarshal = Expression.Condition(
80                 Expression.Equal(value, Expression.Constant(IntPtr.Zero)),
81                 Expression.Constant(null),
82                 Expression.Call(
83                     typeof(Marshal).GetMethod("GetObjectForIUnknown"),
84                     value
85                 )
86             );
87
88             if (_isWrapper) {
89                 unmarshal = Expression.New(
90                     typeof(DispatchWrapper).GetConstructor(new Type[] { typeof(object) }),
91                     unmarshal
92                 );
93             }
94
95             return base.UnmarshalFromRef(unmarshal);
96
97         }
98     }
99 }
100
101 #endif