Skip to content
This repository has been archived by the owner on Jan 29, 2021. It is now read-only.

Commit

Permalink
1.2.0.0: Resolve private members by walking up the inheritance chain.
Browse files Browse the repository at this point in the history
Contributed by Manuel Josupeit-Walter <josupeit-walter@cis-gmbh.de>
  • Loading branch information
skolima committed Mar 6, 2013
1 parent 817a8fe commit 64603e7
Show file tree
Hide file tree
Showing 9 changed files with 175 additions and 37 deletions.
68 changes: 55 additions & 13 deletions ExposedObject/MetaObject.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,30 @@
using System;
// Author:
// Leszek Ciesielski (skolima@gmail.com)
// Manuel Josupeit-Walter (josupeit-walter@cis-gmbh.de)
//
// (C) 2013 Cognifide
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//

using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq.Expressions;
Expand Down Expand Up @@ -64,7 +90,14 @@ public override DynamicMetaObject BindInvokeMember(InvokeMemberBinder binder, Dy
}

var type = exposed.SubjectType;
var method = type.GetMethod(binder.Name, GetBindingFlags(), null, argTypes, null);
var declaringType = type;
MethodInfo method;
do
{
method = declaringType.GetMethod(binder.Name, GetBindingFlags(), null, argTypes, null);
}
while (method == null && (declaringType = declaringType.BaseType) != null);

if (method == null)
{
throw new MissingMemberException(type.FullName, binder.Name);
Expand Down Expand Up @@ -144,25 +177,34 @@ public override DynamicMetaObject BindSetMember(SetMemberBinder binder, DynamicM
/// </exception>
private MemberExpression GetMemberExpression(Expression self, string memberName)
{
MemberExpression memberExpression;
MemberExpression memberExpression = null;
var type = ((Exposed)Value).SubjectType;
var @this = isStatic
? null
: Expression.Convert(Expression.Field(Expression.Convert(self, typeof(Exposed)), "value"), type);
var property = type.GetProperty(memberName, GetBindingFlags());
if (property != null)
{
memberExpression = Expression.Property(@this, property);
}
else
var declaringType = type;

do
{
var field = type.GetField(memberName, GetBindingFlags());
if (field == null)
var property = declaringType.GetProperty(memberName, GetBindingFlags());
if (property != null)
{
memberExpression = Expression.Property(@this, property);
}
else
{
throw new MissingMemberException(type.FullName, memberName);
var field = declaringType.GetField(memberName, GetBindingFlags());
if (field != null)
{
memberExpression = Expression.Field(@this, field);
}
}
}
while (memberExpression == null && (declaringType = declaringType.BaseType) != null);

memberExpression = Expression.Field(@this, field);
if (memberExpression == null)
{
throw new MissingMemberException(type.FullName, memberName);
}

return memberExpression;
Expand Down
8 changes: 4 additions & 4 deletions ExposedObject/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Author:
// Leszek Ciesielski (skolima@gmail.com)
//
// (C) 2011 Cognifide
// (C) 2013 Cognifide
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
Expand Down Expand Up @@ -35,7 +35,7 @@
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Cognifide")]
[assembly: AssemblyProduct("ExposedObject")]
[assembly: AssemblyCopyright("Copyright © Cognifide 2011")]
[assembly: AssemblyCopyright("Copyright © Cognifide 2013")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

Expand All @@ -57,6 +57,6 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.1.0.0")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyVersion("1.2.0.0")]
[assembly: AssemblyFileVersion("1.2.0.0")]
[assembly: CLSCompliant(true)]
7 changes: 5 additions & 2 deletions TestSubjects/ClassWithHiddenMethods.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
// Author:
// Leszek Ciesielski (skolima@gmail.com)
// Manuel Josupeit-Walter (josupeit-walter@cis-gmbh.de)
//
// (C) 2011 Cognifide
// (C) 2013 Cognifide
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
Expand Down Expand Up @@ -29,7 +30,9 @@ namespace TestSubjects
{
public class ClassWithHiddenMethods
{
private int Count { get; set; }
private int _count;

private int Count { get { return _count; } set { _count = value; } }

protected string password;

Expand Down
33 changes: 33 additions & 0 deletions TestSubjects/ClassWithInheritedPrivateMembers.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Author:
// Leszek Ciesielski (skolima@gmail.com)
// Manuel Josupeit-Walter (josupeit-walter@cis-gmbh.de)
//
// (C) 2013 Cognifide
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//

namespace TestSubjects
{
public class ClassWithInheritedPrivateMembers : ClassWithHiddenMethods
{

}
}
8 changes: 4 additions & 4 deletions TestSubjects/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Author:
// Leszek Ciesielski (skolima@gmail.com)
//
// (C) 2011 Cognifide
// (C) 2013 Cognifide
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
Expand Down Expand Up @@ -34,7 +34,7 @@
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Cognifide")]
[assembly: AssemblyProduct("TestSubjects")]
[assembly: AssemblyCopyright("Copyright © Cognifide 2011")]
[assembly: AssemblyCopyright("Copyright © Cognifide 2013")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

Expand All @@ -56,5 +56,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.1.0.0")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyVersion("1.2.0.0")]
[assembly: AssemblyFileVersion("1.2.0.0")]
1 change: 1 addition & 0 deletions TestSubjects/TestSubjects.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
</PropertyGroup>
<ItemGroup>
<Compile Include="ClassWithHiddenMethods.cs" />
<Compile Include="ClassWithInheritedPrivateMembers.cs" />
<Compile Include="GenericMethodClass.cs" />
<Compile Include="HiddenClass.cs" />
<Compile Include="OverloadedMethodsClass.cs" />
Expand Down
67 changes: 67 additions & 0 deletions Tests/ClassWithInheritedPrivateMembersTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// Author:
// Leszek Ciesielski (skolima@gmail.com)
// Manuel Josupeit-Walter (josupeit-walter@cis-gmbh.de)
//
// (C) 2013 Cognifide
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//

using ExposedObject;
using NUnit.Framework;
using TestSubjects;

namespace Tests
{
[TestFixture]
public class ClassWithInheritedPrivateMembersTest
{
[Test]
public void PrivatePropertyTest()
{
dynamic exposed = Exposed.From(new ClassWithInheritedPrivateMembers());
int count = exposed.Count;
Assert.AreEqual(0, count);
exposed.Count = 8;
count = exposed.Count;
Assert.AreEqual(8, count);
}

[Test]
public void PrivateMethodTest()
{
dynamic exposed = Exposed.From(new ClassWithInheritedPrivateMembers());
exposed.SetPassword("test pass");
string password = exposed.Password;
Assert.AreEqual("test pass", password);
}

[Test]
public void PrivateFieldTest()
{
dynamic exposed = Exposed.From(new ClassWithInheritedPrivateMembers());
int count = exposed._count;
Assert.AreEqual(0, count);
exposed._count = 8;
count = exposed.Count;
Assert.AreEqual(8, count);
}
}
}
12 changes: 2 additions & 10 deletions Tests/HiddenClassTest.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
// Author:
// Leszek Ciesielski (skolima@gmail.com)
// Manuel Josupeit-Walter (josupeit-walter@cis-gmbh.de)
//
// (C) 2011 Cognifide
// (C) 2013 Cognifide
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
Expand Down Expand Up @@ -55,15 +56,6 @@ public void MethodTest()
Assert.AreEqual(password, exposed.Password);
}

[Test]
[ExpectedException(typeof(MissingMemberException))]
public void PropertyFailedTest()
{
dynamic exposed = Exposed.New(Type.GetType("TestSubjects.HiddenClass, TestSubjects"));
int count = exposed.Count;
Assert.Fail("Private field is not accessible from a child class.");
}

[Test]
public void PropertyTest()
{
Expand Down
8 changes: 4 additions & 4 deletions Tests/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Author:
// Leszek Ciesielski (skolima@gmail.com)
//
// (C) 2011 Cognifide
// (C) 2013 Cognifide
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
Expand Down Expand Up @@ -34,7 +34,7 @@
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Cognifide")]
[assembly: AssemblyProduct("Tests")]
[assembly: AssemblyCopyright("Copyright © Cognifide 2011")]
[assembly: AssemblyCopyright("Copyright © Cognifide 2013")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

Expand All @@ -56,5 +56,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.1.0.0")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyVersion("1.2.0.0")]
[assembly: AssemblyFileVersion("1.2.0.0")]

0 comments on commit 64603e7

Please sign in to comment.