- Delay calling convention patching until Bake (because accessors may be set while they aren't done yet).

- Allow multiple getter/setter methods.
- Fixed GetAccessors() regression introduced with recent order retention fixes.
This commit is contained in:
jfrijters 2011-03-10 10:56:57 +00:00
Родитель 1b78725186
Коммит a6fcfae9bd
1 изменённых файлов: 33 добавлений и 44 удалений

Просмотреть файл

@ -1,5 +1,5 @@
/*
Copyright (C) 2008 Jeroen Frijters
Copyright (C) 2008-2011 Jeroen Frijters
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -37,10 +37,16 @@ namespace IKVM.Reflection.Emit
private PropertySignature sig;
private MethodBuilder getter;
private MethodBuilder setter;
private readonly List<MethodBuilder> accessors = new List<MethodBuilder>();
private readonly List<Accessor> accessors = new List<Accessor>();
private int lazyPseudoToken;
private bool patchCallingConvention;
private struct Accessor
{
internal short Semantics;
internal MethodBuilder Method;
}
internal PropertyBuilder(TypeBuilder typeBuilder, string name, PropertyAttributes attributes, PropertySignature sig, bool patchCallingConvention)
{
this.typeBuilder = typeBuilder;
@ -55,34 +61,30 @@ namespace IKVM.Reflection.Emit
get { return sig; }
}
private void PatchCallingConvention(MethodBuilder mdBuilder)
{
if (patchCallingConvention && !mdBuilder.IsStatic)
{
sig.HasThis = true;
}
}
public void SetGetMethod(MethodBuilder mdBuilder)
{
PatchCallingConvention(mdBuilder);
accessors.Remove(getter);
getter = mdBuilder;
accessors.Add(mdBuilder);
Accessor acc;
acc.Semantics = MethodSemanticsTable.Getter;
acc.Method = mdBuilder;
accessors.Add(acc);
}
public void SetSetMethod(MethodBuilder mdBuilder)
{
PatchCallingConvention(mdBuilder);
accessors.Remove(setter);
setter = mdBuilder;
accessors.Add(mdBuilder);
Accessor acc;
acc.Semantics = MethodSemanticsTable.Setter;
acc.Method = mdBuilder;
accessors.Add(acc);
}
public void AddOtherMethod(MethodBuilder mdBuilder)
{
PatchCallingConvention(mdBuilder);
accessors.Add(mdBuilder);
Accessor acc;
acc.Semantics = MethodSemanticsTable.Other;
acc.Method = mdBuilder;
accessors.Add(acc);
}
public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
@ -144,14 +146,9 @@ namespace IKVM.Reflection.Emit
public override MethodInfo[] GetAccessors(bool nonPublic)
{
List<MethodInfo> list = new List<MethodInfo>();
AddAccessor(list, nonPublic, getter);
AddAccessor(list, nonPublic, setter);
if (accessors != null)
foreach (Accessor acc in accessors)
{
foreach (MethodInfo method in accessors)
{
AddAccessor(list, nonPublic, method);
}
AddAccessor(list, nonPublic, acc.Method);
}
return list.ToArray();
}
@ -191,6 +188,11 @@ namespace IKVM.Reflection.Emit
internal void Bake()
{
if (patchCallingConvention)
{
sig.HasThis = !this.IsStatic;
}
PropertyTable.Record rec = new PropertyTable.Record();
rec.Flags = (short)attributes;
rec.Name = typeBuilder.ModuleBuilder.Strings.Add(name);
@ -202,22 +204,9 @@ namespace IKVM.Reflection.Emit
typeBuilder.ModuleBuilder.RegisterTokenFixup(lazyPseudoToken, token);
}
foreach (MethodBuilder method in accessors)
foreach (Accessor acc in accessors)
{
short semantics;
if (method == getter)
{
semantics = MethodSemanticsTable.Getter;
}
else if (method == setter)
{
semantics = MethodSemanticsTable.Setter;
}
else
{
semantics = MethodSemanticsTable.Other;
}
AddMethodSemantics(semantics, method.MetadataToken, token);
AddMethodSemantics(acc.Semantics, acc.Method.MetadataToken, token);
}
}
@ -234,9 +223,9 @@ namespace IKVM.Reflection.Emit
{
get
{
foreach (MethodBuilder method in accessors)
foreach (Accessor acc in accessors)
{
if (method.IsPublic)
if (acc.Method.IsPublic)
{
return true;
}
@ -249,9 +238,9 @@ namespace IKVM.Reflection.Emit
{
get
{
foreach (MethodBuilder method in accessors)
foreach (Accessor acc in accessors)
{
if (method.IsStatic)
if (acc.Method.IsStatic)
{
return true;
}