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
18 using System
.Reflection
;
19 using System
.Reflection
.Emit
;
21 public class PropertyEmitter
: IMemberEmitter
23 private PropertyBuilder builder
;
24 private AbstractTypeEmitter parentTypeEmitter
;
25 private MethodEmitter getMethod
;
26 private MethodEmitter setMethod
;
28 private static readonly MethodInfo newDefinePropertyMethodInfo
= typeof (TypeBuilder
).GetMethod("DefineProperty", new Type
[]
30 typeof (string), typeof (PropertyAttributes
),
31 typeof (CallingConventions
), typeof (Type
),
32 typeof (Type
[]), typeof (Type
[]), typeof (Type
[]),
33 typeof (Type
[][]), typeof (Type
[][])
36 // private ParameterInfo[] indexParameters;
38 private delegate PropertyBuilder
DefineProperty_Clr2_0(
39 string name
, PropertyAttributes attributes
, Type propertyType
, Type
[] parameters
);
41 public delegate PropertyBuilder
DefineProperty_Clr_2_0_SP1(string name
,
42 PropertyAttributes attributes
,
43 CallingConventions callingConvention
,
45 Type
[] returnTypeRequiredCustomModifiers
,
46 Type
[] returnTypeOptionalCustomModifiers
,
47 Type
[] parameterTypes
,
48 Type
[][] parameterTypeRequiredCustomModifiers
,
49 Type
[][] parameterTypeOptionalCustomModifiers
);
51 public PropertyEmitter(AbstractTypeEmitter parentTypeEmitter
, String name
, PropertyAttributes attributes
,
54 this.parentTypeEmitter
= parentTypeEmitter
;
56 // DYNPROXY-73 - AmbiguousMatchException for properties
57 // This is a workaround for a framework limitation in CLR 2.0
58 // This limitation was removed in CLR 2.0 SP1, but we don't want to
59 // tie ourselves to that version. This perform the lookup for the new overload
60 // dynamically, so we have a nice fallback on vanilla CLR 2.0
61 DefineProperty_Clr2_0 oldDefineProperty
= parentTypeEmitter
.TypeBuilder
.DefineProperty
;
62 DefineProperty_Clr_2_0_SP1 newDefinedProperty
= (DefineProperty_Clr_2_0_SP1
)
63 Delegate
.CreateDelegate(typeof(DefineProperty_Clr_2_0_SP1
), parentTypeEmitter
.TypeBuilder
, newDefinePropertyMethodInfo
);
65 if(newDefinedProperty
==null)
67 builder
= oldDefineProperty(name
, attributes
, propertyType
, new Type
[0]);
71 builder
= parentTypeEmitter
.TypeBuilder
.DefineProperty(
72 name
, attributes
, CallingConventions
.HasThis
, propertyType
,
73 null, null, new Type
[0], null, null);
77 public MethodEmitter GetMethod
79 get { return getMethod; }
80 set { getMethod = value; }
83 public MethodEmitter SetMethod
85 get { return setMethod; }
86 set { setMethod = value; }
89 public MethodEmitter
CreateGetMethod()
91 return CreateGetMethod(MethodAttributes
.Public
|
92 MethodAttributes
.Virtual
|
93 MethodAttributes
.SpecialName
);
96 public MethodEmitter
CreateGetMethod(MethodAttributes attrs
, params Type
[] parameters
)
98 if (getMethod
!= null)
100 throw new InvalidOperationException("A getMethod exists");
103 if (parameters
.Length
== 0)
105 getMethod
= new MethodEmitter(parentTypeEmitter
, "get_" + builder
.Name
, attrs
);
109 getMethod
= new MethodEmitter(parentTypeEmitter
, "get_" + builder
.Name
,
118 public MethodEmitter
CreateSetMethod()
120 return CreateSetMethod(MethodAttributes
.Public
|
121 MethodAttributes
.Virtual
|
122 MethodAttributes
.SpecialName
);
125 public MethodEmitter
CreateSetMethod(Type arg
)
127 return CreateSetMethod(MethodAttributes
.Public
|
128 MethodAttributes
.Virtual
|
129 MethodAttributes
.SpecialName
, arg
);
132 public MethodEmitter
CreateSetMethod(MethodAttributes attrs
, params Type
[] parameters
)
134 if (setMethod
!= null)
136 throw new InvalidOperationException("A setMethod exists");
139 if (parameters
.Length
== 0)
141 setMethod
= new MethodEmitter(parentTypeEmitter
, "set_" + builder
.Name
, attrs
);
145 setMethod
= new MethodEmitter(parentTypeEmitter
, "set_" + builder
.Name
,
146 attrs
, typeof (void),
153 public MemberInfo Member
158 public Type ReturnType
160 get { return builder.PropertyType; }
163 public void Generate()
165 if (setMethod
!= null)
167 setMethod
.Generate();
168 builder
.SetSetMethod(setMethod
.MethodBuilder
);
171 if (getMethod
!= null)
173 getMethod
.Generate();
174 builder
.SetGetMethod(getMethod
.MethodBuilder
);
178 public void EnsureValidCodeBlock()
180 if (setMethod
!= null)
182 setMethod
.EnsureValidCodeBlock();
185 if (getMethod
!= null)
187 getMethod
.EnsureValidCodeBlock();