System.Linq.Dynamic.Core
System.Linq.Dynamic.Core copied to clipboard
Documentation: limitations of type usage to accessible types is incorrectly stated
From the documentation:
| Category | Expression | Description |
|---|---|---|
| Primary | x.m |
Instance field or property access. Any public field or property can be accessed. |
| Primary | x.m(...) |
Instance method invocation. The method must be public and must be declared in an accessible type. |
| ... | ... | ... |
| Primary | T.m |
Static field or static property access. Any public field or property can be accessed. |
| Primary | T.m(...) |
Static method invocation. The method must be public and must be declared in an accessible type. |
This is incorrect:
- All instance methods are allowed, not just the instance methods on an accessible type
public class Foo { public string TestMethod() => ""; } // runs successfully var results = (new List<Foo>()).AsQueryable().Where("TestMethod() = \"\"").ToArray(); - Like static methods, static fields or properties are only allowed on accessible types; not any public field or property can be accessed
public static class Bar {
public readonly static string EmptyString = "";
}
// fails: System.Linq.Dynamic.Core.Exceptions.ParseException: 'No property or field 'Bar' exists in type 'String''
var results = (new List<string>()).AsQueryable().Where("it = Bar.EmptyString").ToArray();
@JonathanMagnan
Apparently, things are not so simple. Instance methods are allowed only if either the instance type is an accessible type, or the return type is an accessible type. So this code:
public class Person {
public void Notify() { }
public bool Notify1() => true;
public Person Notify2() => null;
}
var selectors = new[] {
"Notify()",
"Notify1()",
"Notify2()"
};
foreach (var selector in selectors) {
Console.WriteLine(selector);
try {
var prm = Parameter(typeof(Person));
var parser = new ExpressionParser(new[] { prm }, selector, new object[] { }, ParsingConfig.Default);
var expr = parser.Parse(null);
Console.WriteLine("(success)");
} catch (Exception ex) {
Console.WriteLine(ex.Message);
}
Console.WriteLine();
}
outputs this:
Notify()
Methods on type 'Person' are not accessible
Notify1()
(success)
Notify2()
Methods on type 'Person' are not accessible
because Notify's return type is void, while Notify2's return type is Person. Only Notify1's return type is an accessible type -- bool (Source).
(NB. I see that there's also an explicit exclusion for void-returning methods, even if the instance type is accessible.)
Is this behavior by design?
Also, I would add that unlike instance methods, indexers can return an inaccessible type.