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 lazyPseudoToken = token;
208 typeBuilder.ModuleBuilder.RegisterTokenFixup(lazyPseudoToken, token);
211 foreach (Accessor acc in accessors)
213 AddMethodSemantics(acc.Semantics, acc.Method.MetadataToken, token);
217 private void AddMethodSemantics(short semantics, int methodToken, int propertyToken)
219 MethodSemanticsTable.Record rec = new MethodSemanticsTable.Record();
220 rec.Semantics = semantics;
221 rec.Method = methodToken;
222 rec.Association = propertyToken;
223 typeBuilder.ModuleBuilder.MethodSemantics.AddRecord(rec);
226 internal override bool IsPublic
230 foreach (Accessor acc in accessors)
232 if (acc.Method.IsPublic)
241 internal override bool IsNonPrivate
245 foreach (Accessor acc in accessors)
247 if ((acc.Method.Attributes & MethodAttributes.MemberAccessMask) > MethodAttributes.Private)
256 internal override bool IsStatic
260 foreach (Accessor acc in accessors)
262 if (acc.Method.IsStatic)
271 internal override bool IsBaked
273 get { return typeBuilder.IsBaked; }
276 internal override int GetCurrentToken()
278 if (typeBuilder.ModuleBuilder.IsSaved && typeBuilder.ModuleBuilder.IsPseudoToken(lazyPseudoToken))
280 return typeBuilder.ModuleBuilder.ResolvePseudoToken(lazyPseudoToken);
284 return lazyPseudoToken;