Skip to content

Commit

Permalink
Merge branch 'issue-52' of https://github.com/hVostt/fast-member into…
Browse files Browse the repository at this point in the history
… hVostt-issue-52

# Conflicts:
#	FastMember.Tests/BasicTests.cs
  • Loading branch information
mgravell committed May 24, 2019
2 parents cf3b6f2 + 4114abe commit 458ac40
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 23 deletions.
17 changes: 16 additions & 1 deletion FastMember.Tests/BasicTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -330,10 +330,13 @@ public class MixedAccess
{
public MixedAccess()
{
Foo = Bar = 2;
Foo = Bar = Alpha = Beta = 2;
}
public int Foo { get; private set; }
public int Bar { private get; set; }
public readonly int Alpha;
public int Beta { get; }
public int Theta { get { return 5; } }
}

[Fact]
Expand All @@ -357,6 +360,10 @@ public void TestMixedAccess()
Assert.Equal(4, acc2[obj, "Bar"]);
acc2[obj, "Foo"] = 5;
Assert.Equal(5, acc0[obj, "Foo"]);
acc2[obj, "Alpha"] = 6;
Assert.Equal(6, acc2[obj, "Alpha"]);
acc2[obj, "Beta"] = 7;
Assert.Equal(7, acc2[obj, "Beta"]);

Assert.Throws<ArgumentOutOfRangeException>(() =>
{
Expand All @@ -366,6 +373,14 @@ public void TestMixedAccess()
{
acc0[obj, "Foo"] = 6;
});
Assert.Throws<ArgumentOutOfRangeException>(() =>
{
acc0[obj, "Beta"] = 7;
});
Assert.Throws<ArgumentOutOfRangeException>(() =>
{
acc0[obj, "Theta"] = 8;
});
}

public class ObjectReaderType {
Expand Down
61 changes: 39 additions & 22 deletions FastMember/TypeAccessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ private static void WriteMapImpl(ILGenerator il, Type type, List<MemberInfo> mem
il.Emit(OpCodes.Ldloca_S, (byte)0);
il.EmitCall(OpCodes.Callvirt, tryGetValue, null);
il.Emit(OpCodes.Brfalse, fail);
}
}
Label[] labels = new Label[members.Count];
for (int i = 0; i < labels.Length; i++)
{
Expand All @@ -129,29 +129,34 @@ private static void WriteMapImpl(ILGenerator il, Type type, List<MemberInfo> mem
il.MarkLabel(labels[i]);
var member = members[i];
bool isFail = true;
FieldInfo field;
PropertyInfo prop;
if((field = member as FieldInfo) != null)

void WriteField(FieldInfo fieldToWrite)
{
il.Emit(obj);
Cast(il, type, true);
if (isGet)
{
il.Emit(OpCodes.Ldfld, field);
if (field.FieldType.IsValueType) il.Emit(OpCodes.Box, field.FieldType);
}
else
if (!fieldToWrite.FieldType.IsByRef)
{
il.Emit(value);
Cast(il, field.FieldType, false);
il.Emit(OpCodes.Stfld, field);
il.Emit(obj);
Cast(il, type, true);
if (isGet)
{
il.Emit(OpCodes.Ldfld, fieldToWrite);
if (fieldToWrite.FieldType.IsValueType) il.Emit(OpCodes.Box, fieldToWrite.FieldType);
}
else
{
il.Emit(value);
Cast(il, fieldToWrite.FieldType, false);
il.Emit(OpCodes.Stfld, fieldToWrite);
}
il.Emit(OpCodes.Ret);
isFail = false;
}
il.Emit(OpCodes.Ret);
isFail = false;
}
else if ((prop = member as PropertyInfo) != null)
if (member is FieldInfo field)
{
WriteField(field);
}
else if (member is PropertyInfo prop)
{
MethodInfo accessor;
var propType = prop.PropertyType;
bool isByRef = propType.IsByRef, isValid = true;
if (isByRef)
Expand All @@ -163,11 +168,23 @@ private static void WriteMapImpl(ILGenerator il, Type type, List<MemberInfo> mem
propType = propType.GetElementType(); // from "ref Foo" to "Foo"
}

if (isValid && prop.CanRead && (accessor = (isGet | isByRef) ? prop.GetGetMethod(allowNonPublicAccessors) : prop.GetSetMethod(allowNonPublicAccessors)) != null)
var accessor = (isGet | isByRef) ? prop.GetGetMethod(allowNonPublicAccessors) : prop.GetSetMethod(allowNonPublicAccessors);
if (accessor == null && allowNonPublicAccessors && !isByRef)
{
// No getter/setter, use backing field instead if it exists
var backingField = $"<{prop.Name}>k__BackingField";
field = prop.DeclaringType?.GetField(backingField, BindingFlags.Instance | BindingFlags.NonPublic);

if (field != null)
{
WriteField(field);
}
}
else if (isValid && prop.CanRead && accessor != null)
{
il.Emit(obj);
Cast(il, type, true); // cast the input object to the right target type

if (isGet)
{
il.EmitCall(type.IsValueType ? OpCodes.Call : OpCodes.Callvirt, accessor, null);
Expand Down Expand Up @@ -422,4 +439,4 @@ private static void Cast(ILGenerator il, Type type, bool valueAsPointer)
set;
}
}
}
}

0 comments on commit 458ac40

Please sign in to comment.