1 // Copyright 2004-2007 Castle Project - http://www.castleproject.org/
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
7 // http://www.apache.org/licenses/LICENSE-2.0
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
.Generators
.Emitters
.SimpleAST
18 using System
.Reflection
.Emit
;
20 public class ConvertExpression
: Expression
22 private readonly Expression right
;
23 private Type fromType
;
26 public ConvertExpression(Type targetType
, Expression right
)
27 : this(targetType
, typeof(object), right
)
31 public ConvertExpression(Type targetType
, Type fromType
, Expression right
)
34 this.fromType
= fromType
;
38 public override void Emit(IMemberEmitter member
, ILGenerator gen
)
40 right
.Emit(member
, gen
);
42 if (fromType
== target
)
49 fromType
= fromType
.GetElementType();
54 target
= target
.GetElementType();
57 if (target
.IsValueType
)
59 if (fromType
.IsValueType
)
61 throw new NotImplementedException("Cannot convert between distinct value types");
66 // Assumes fromType is a boxed value
67 // if we can, we emit a box and ldind, otherwise, we will use unbox.any
68 if (LdindOpCodesDictionary
.Instance
[target
] != LdindOpCodesDictionary
.EmptyOpCode
)
70 gen
.Emit(OpCodes
.Unbox
, target
);
71 OpCodeUtil
.EmitLoadIndirectOpCodeForType(gen
, target
);
75 gen
.Emit(OpCodes
.Unbox_Any
, target
);
81 if (fromType
.IsValueType
)
84 gen
.Emit(OpCodes
.Box
, fromType
);
85 EmitCastIfNeeded(typeof(object), target
, gen
);
90 EmitCastIfNeeded(fromType
, target
, gen
);
95 private static void EmitCastIfNeeded(Type
from, Type target
, ILGenerator gen
)
97 if (target
.IsGenericParameter
)
99 gen
.Emit(OpCodes
.Unbox_Any
, target
);
101 else if (from.IsGenericParameter
)
103 gen
.Emit(OpCodes
.Box
, from);
105 else if (target
.IsGenericType
&& target
!= from)
107 gen
.Emit(OpCodes
.Castclass
, target
);
109 else if (target
.IsSubclassOf(from))
111 gen
.Emit(OpCodes
.Castclass
, target
);