Skip to content

Commit

Permalink
Merge pull request #1522 from riganti/fix/binding-private-members
Browse files Browse the repository at this point in the history
MemberExpressionFactory filters out private members
  • Loading branch information
exyi committed Dec 2, 2022
2 parents 432bf6f + 7c704eb commit c81853d
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public MemberExpressionFactory(ExtensionMethodsCache extensionMethodsCache, IRea
catch { }

var members = new List<MemberInfo>();
foreach (var m in type.GetAllMembers())
foreach (var m in type.GetAllMembers(bindingFlags))
if (((isGeneric && m is TypeInfo) ? genericName : name) == m.Name)
members.Add(m);

Expand All @@ -72,7 +72,15 @@ public MemberExpressionFactory(ExtensionMethodsCache extensionMethodsCache, IRea
}

if (members.Count == 0 && throwExceptions)
{
var privateMember = type.GetAllMembers(bindingFlags | BindingFlags.NonPublic).Where(m => m.Name == name).FirstOrDefault();
if (privateMember is {})
throw new Exception($"{ (isStatic ? "Static" : "Instance") } member '{privateMember}' is private, please make it public to use it in the binding.");
var staticMember = type.GetAllMembers(bindingFlags | BindingFlags.Static | BindingFlags.Instance).Where(m => m.Name == name).FirstOrDefault();
if (staticMember is {})
throw new Exception($"Member '{staticMember}' is {(isStatic ? "not static" : "static")}.");
throw new Exception($"Could not find { (isStatic ? "static" : "instance") } member { name } on type { type.FullName }.");
}
else if (members.Count == 0 && !throwExceptions)
return null;
}
Expand Down
24 changes: 24 additions & 0 deletions src/Tests/Binding/ExpressionHelperTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,15 @@
using Microsoft.CSharp.RuntimeBinder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using CheckTestOutput;
using DotVVM.Framework.Tests.Runtime;

namespace DotVVM.Framework.Tests.Binding
{
[TestClass]
public class ExpressionHelperTests
{
OutputChecker check = new CheckTestOutput.OutputChecker("testoutputs");
public TestContext TestContext { get; set; }
private MemberExpressionFactory memberExpressionFactory;

Expand Down Expand Up @@ -278,6 +281,20 @@ public void Call_FindOverload_Params_Generic_Array_Invalid(Type resultIdentifier
Call_FindOverload_Generic(typeof(MethodsParamsArgumentsGenericResolvingSampleObject),
MethodsParamsArgumentsGenericResolvingSampleObject.MethodName, argTypes, resultIdentifierType, expectedArgsTypes);
}

[TestMethod]
[DataRow("PrivateField", "Instance member 'System.String PrivateField' is private, please make it public to use it in the binding.")]
[DataRow("PrivateProperty", "Instance member 'System.String PrivateProperty' is private, please make it public to use it in the binding.")]
[DataRow("StaticProperty", "Member 'System.String StaticProperty' is static.")]
public void Error_MemberPrivate(string memberName, string error)
{
var ex = Assert.ThrowsException<Exception>(() =>
memberExpressionFactory.GetMember(
Expression.Parameter(typeof(ErrorSampleObject), "vm"),
memberName
));
Assert.AreEqual(error, ex.Message);
}
}
public static class MethodsParamsArgumentsGenericResolvingSampleObject
{
Expand Down Expand Up @@ -337,6 +354,13 @@ public class GenericModelSampleObject<T>
public T Prop { get; set; }
}

public class ErrorSampleObject
{
private string PrivateField;
private string PrivateProperty { get; }
public static string StaticProperty { get; }
}

public class GenericTestResult1 { }
public class GenericTestResult2 { }
public class GenericTestResult3 { }
Expand Down
2 changes: 1 addition & 1 deletion src/Tests/Binding/StaticCommandCompilationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ public void StaticCommandCompilation_FailReasonablyOnInvalidMethod()

var result = Assert.ThrowsException<BindingPropertyException>(() => CompileBinding("TestViewModel.GetCharCode", false, typeof(TestViewModel)));

Assert.AreEqual("Static method 'TestViewModel.GetCharCode' not found, but an instance method exists.", result.GetBaseException().Message);
Assert.AreEqual("Member 'Int32 GetCharCode(Char)' is not static.", result.GetBaseException().Message);
}

public void AreEqual(string expected, string actual)
Expand Down

0 comments on commit c81853d

Please sign in to comment.