2 Copyright (C) 2008-2011 Jeroen Frijters
4 This software is provided 'as-is', without any express or implied
5 warranty. In no event will the authors be held liable for any damages
6 arising from the use of this software.
8 Permission is granted to anyone to use this software for any purpose,
9 including commercial applications, and to alter it and redistribute it
10 freely, subject to the following restrictions:
12 1. The origin of this software must not be misrepresented; you must not
13 claim that you wrote the original software. If you use this software
14 in a product, an acknowledgment in the product documentation would be
15 appreciated but is not required.
16 2. Altered source versions must be plainly marked as such, and must not be
17 misrepresented as being the original software.
18 3. This notice may not be removed or altered from any source distribution.
25 using System.Collections.Generic;
26 using System.Runtime.CompilerServices;
27 using IKVM.Reflection.Writer;
28 using IKVM.Reflection.Metadata;
30 namespace IKVM.Reflection.Emit
32 public sealed class PropertyBuilder : PropertyInfo
34 private readonly TypeBuilder typeBuilder;
35 private readonly string name;
36 private PropertyAttributes attributes;
37 private PropertySignature sig;
38 private MethodBuilder getter;
39 private MethodBuilder setter;
40 private readonly List<Accessor> accessors = new List<Accessor>();
41 private int lazyPseudoToken;
42 private bool patchCallingConvention;
44 private struct Accessor
46 internal short Semantics;
47 internal MethodBuilder Method;
50 internal PropertyBuilder(TypeBuilder typeBuilder, string name, PropertyAttributes attributes, PropertySignature sig, bool patchCallingConvention)
52 this.typeBuilder = typeBuilder;
54 this.attributes = attributes;
56 this.patchCallingConvention = patchCallingConvention;
59 internal override PropertySignature PropertySignature
64 public void SetGetMethod(MethodBuilder mdBuilder)
68 acc.Semantics = MethodSemanticsTable.Getter;
69 acc.Method = mdBuilder;
73 public void SetSetMethod(MethodBuilder mdBuilder)
77 acc.Semantics = MethodSemanticsTable.Setter;
78 acc.Method = mdBuilder;
82 public void AddOtherMethod(MethodBuilder mdBuilder)
85 acc.Semantics = MethodSemanticsTable.Other;
86 acc.Method = mdBuilder;
90 public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
92 SetCustomAttribute(new CustomAttributeBuilder(con, binaryAttribute));
95 public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
97 Universe u = typeBuilder.ModuleBuilder.universe;
98 if (customBuilder.Constructor.DeclaringType == u.System_Runtime_CompilerServices_SpecialNameAttribute)
100 attributes |= PropertyAttributes.SpecialName;
104 if (lazyPseudoToken == 0)
106 lazyPseudoToken = typeBuilder.ModuleBuilder.AllocPseudoToken();
108 typeBuilder.ModuleBuilder.SetCustomAttribute(lazyPseudoToken, customBuilder);
112 public override object GetRawConstantValue()
114 if (lazyPseudoToken != 0)
116 return typeBuilder.ModuleBuilder.Constant.GetRawConstantValue(typeBuilder.ModuleBuilder, lazyPseudoToken);
118 throw new InvalidOperationException();
121 public override PropertyAttributes Attributes
123 get { return attributes; }
126 public override bool CanRead
128 get { return getter != null; }
131 public override bool CanWrite
133 get { return setter != null; }
136 public override MethodInfo GetGetMethod(bool nonPublic)
138 return nonPublic || (getter != null && getter.IsPublic) ? getter : null;
141 public override MethodInfo GetSetMethod(bool nonPublic)
143 return nonPublic || (setter != null && setter.IsPublic) ? setter : null;
146 public override MethodInfo[] GetAccessors(bool nonPublic)
148 List<MethodInfo> list = new List<MethodInfo>();
149 foreach (Accessor acc in accessors)
151 AddAccessor(list, nonPublic, acc.Method);
153 return list.ToArray();
156 private static void AddAccessor(List<MethodInfo> list, bool nonPublic, MethodInfo method)
158 if (method != null && (nonPublic || method.IsPublic))
164 public override Type DeclaringType
166 get { return typeBuilder; }
169 public override string Name
174 public override Module Module
176 get { return typeBuilder.Module; }
179 public void SetConstant(object defaultValue)
181 if (lazyPseudoToken == 0)
183 lazyPseudoToken = typeBuilder.ModuleBuilder.AllocPseudoToken();
185 attributes |= PropertyAttributes.HasDefault;
186 typeBuilder.ModuleBuilder.AddConstant(lazyPseudoToken, defaultValue);
191 if (patchCallingConvention)
193 sig.HasThis = !this.IsStatic;
196 PropertyTable.Record rec = new PropertyTable.Record();
197 rec.Flags = (short)attributes;
198 rec.Name = typeBuilder.ModuleBuilder.Strings.Add(name);
199 rec.Type = typeBuilder.ModuleBuilder.GetSignatureBlobIndex(sig);
200 int token = 0x17000000 | typeBuilder.ModuleBuilder.Property.AddRecord(rec);
202 if (lazyPseudoToken != 0)
204 typeBuilder.ModuleBuilder.RegisterTokenFixup(lazyPseudoToken, token);
207 foreach (Accessor acc in accessors)
209 AddMethodSemantics(acc.Semantics, acc.Method.MetadataToken, token);
213 private void AddMethodSemantics(short semantics, int methodToken, int propertyToken)
215 MethodSemanticsTable.Record rec = new MethodSemanticsTable.Record();
216 rec.Semantics = semantics;
217 rec.Method = methodToken;
218 rec.Association = propertyToken;
219 typeBuilder.ModuleBuilder.MethodSemantics.AddRecord(rec);
222 internal override bool IsPublic
226 foreach (Accessor acc in accessors)
228 if (acc.Method.IsPublic)
237 internal override bool IsStatic
241 foreach (Accessor acc in accessors)
243 if (acc.Method.IsStatic)