Access parameter/variable passed to Invoke-call - c#

I'm trying to build some dynamic queries for my underlying database using LinqKit and the expandable-extensions.
In my code I have a property which looks like
private Expression<Func<MyModel, MyConfig, MyResult>> Parent
{
get
{
var modelParam = Expression.Parameter(typeof(MyModel), "myModel");
var configParam = Expression.Parameter(typeof(MyConfig), "config");
var conditionalExpression = Expression.Call(configParam, typeof(MyConfig).GetMethod("ShowParent"), Expression.Constant("SomeName"));
// how to decide whether to return an expression or null?
// build expression or return constant null-expression
}
}
which I call Parent.Invoke(myModel, config).
Is there any chance to gain access to the config-param which is passed to the Invoke-call to determine inside the getter whether to return a real Expression or just null?
The MyConfig class has a method bool ShowParent(string parentName) which I would like to call inside the getter to determine what to do?
Is this possible that way? If not, are there any good points where to start with?

Related

When compiling C# expression trees into methods, is it possible to access "this"?

I am trying to dynamically generate a class that implements a given interface. Because of this, I need to implement some methods. I would like to avoid directly emitting IL instructions, so I am trying to use Expression trees and CompileToMethod. Unfortunately, some of these methods need to access a field of the generated class (as if I wrote this.field into the method I am implementing). Is it possible to access "this" using expression trees? (By "this" I mean the object the method will be called on.)
If yes, what would a method like this look like with expression trees?
int SomeMethod() {
return this.field.SomeOtherMethod();
}
Expression.Constant or ParameterExpression are your friends; examples:
var obj = Expression.Constant(this);
var field = Expression.PropertyOrField(obj, "field");
var call = Expression.Call(field, field.Type.GetMethod("SomeOtherMethod"));
var lambda = Expression.Lambda<Func<int>>(call);
or:
var obj = Expression.Parameter(typeof(SomeType));
var field = Expression.PropertyOrField(obj, "field");
var call = Expression.Call(field, field.Type.GetMethod("SomeOtherMethod"));
var lambda = Expression.Lambda<Func<SomeType, int>>(call, obj);
(in the latter case, you'd pass this in as a parameter, but it means you can store the lambda and re-use it for different target instance objects)
Another option here might be dynamic if your names are fixed:
dynamic obj = someDuckTypedObject;
int i = obj.field.SomeOtherMethod();

Why DapperRow.GetType() return null?

As far as I knew, Object.GetType() should never return null. (related discussion)
Dapper .Query() return private class DapperRow instances to be treated as dynamic objects. I found a strange thing: DapperRow's .GetType() return null.
Here's the sample code to reproduce the problem. Create a C# project, reference Dapper and open a connection to SQL Server (or other database), use .Query() to execute simple select query and retrieve the first row of result. Use GetType() to get the type of result object, the return value is null.
using (SqlConnection cn = new SqlConnection(csSql))
{
var rec = cn.Query("select getdate() as D").Single();
var t = rec.GetType(); // t == null
Console.WriteLine(t.Name); // null reference exception
}
I suspect that dynamic or private type is the cause of null, so I write my class library for test:
namespace Lib
{
public class Blah
{
public static dynamic SecretObject;
static Blah()
{
SecretObject = new PrivateType();
}
}
class PrivateType
{
}
}
In another project, get the dynamic type static field and call GetType():
dynamic obj = Lib.Blah.SecretObject;
Console.WriteLine(obj.GetType().Name); // "Lib.PrivateType"
According to the test result, even cast private type as dynamic, I still can get the private type information from GetType(), why DapperRow.GetType() return null?
DapperRow is specifically built and utilized within Dapper to provide highly optimized row returns without reiterating header information. This is to help condense the size of the object and reduce redundant data, making it more efficient.
However, it would appear that the StackExchange team took the meta programming even further than a first glance would indicate.
DapperRow implements the System.Dynamic.IDynamicMetaObjectProvide interface, which requires that the GetMetaObject method be implemented:
System.Dynamic.DynamicMetaObject System.Dynamic.IDynamicMetaObjectProvider.GetMetaObject(
System.Linq.Expressions.Expression parameter)
{
return new DapperRowMetaObject(parameter,
System.Dynamic.BindingRestrictions.Empty, this);
}
DapperRowMetaObject is a custom implementation of DynamicMetaObject that essentially hijacks and overrides what methods can be invoked against the dynamic type and what those calls should translate to. In this case, calls to anything other than the DapperRow's IDictionary.Item getter or the DapperRow.SetValue will fail since they are always routed to those two calls, but the value will be defaulted to null for any "get" calls where the target property does not exist in the table.
public bool TryGetValue(string name, out object value)
{
var index = table.IndexOfName(name);
if (index < 0)
{ // doesn't exist
value = null;
return false;
}
...
}
At that point, any methods invoked on a null dynamic value will throw a RuntimeBinderException:
RuntimeBinderException: Cannot perform runtime binding on a null
reference
You can easily test this hypothesis by replacing GetType() with another call that will throw the exact same exception:
var rec = cn.Query("select getdate() as D").Single();
var t = rec.AsEnumerable();
Console.WriteLine(t.ToList());
Keep in mind, the underlying type information of any properties on the dynamic object itself can still be accessed directly:
var rec = cn.Query("select getdate() as D").Single();
var t = rec.D.GetType();
Console.WriteLine(t.Name);

Expression<Func<T>> - Get Property's calling object instance without Compile()

EDIT: Updated example to what I'm actually doing.
EDIT 2: The why:
My class "takes hold" of a property setter (or method, anonymous or not) and "controls" it for a period of time. The user could try and attach another instance of my class and attach that to a property that is already "controlled." I need a way to detect these conflicts reliably. I could forego the () => { property } method but that requires the user to wrap the target property in a method and, if he/she wants conflict detection, to pass in the object containing the property. Doing it that way introduces higher risk of bugs as they may type in the wrong object and the class wouldn't have any means to check for them.
I am unable to utilize the Lambda Compile() because I am targeting AOT in addition to JIT.
I have a method that takes an
Expression<Func<T>>
as an argument. The Expression always evaluates to a property with a setter of Type T.
private static TargetInfo GetTargetInfo<T>(Expression<Func<T>> _propertyExpression, out Action<T> _setter)
{
//Get Property info
var propInfo = ((MemberExpression)_propertyExpression.Body).Member as PropertyInfo;
if (propInfo == null)
throw new ArgumentException("_propertyExpression must be a property.");
var declType = propInfo.DeclaringType;
var methodInfo = propInfo.GetSetMethod(true) ?? declType.GetProperty(propInfo.Name).GetSetMethod(true);
if (methodInfo == null)
throw new Exception("Could not create setter from property '" + _propertyExpression + "'");
var isStaticProp = methodInfo.IsStatic;
//Get Target Object
object targetObject = null;
var memberExp = _propertyExpression.Body as MemberExpression;
var bodyExp = memberExp.Expression;
if (bodyExp != null)
// PROBLEM LINE BELOW - Can't use Compile() *********************************
targetObject = Expression.Lambda<Func<object>>(bodyExp).Compile()();
// PROBLEM LINE ABOVE *******************************************************
else if (isStaticProp)
targetObject = memberExp.Member.DeclaringType;
else
throw new Exception("Could not determine target object. Use Action<T> overload. (no conflict detection)");
//Cache setter of property
if (isStaticProp)
_setter = (Action<T>) Delegate.CreateDelegate(typeof (Action<T>), methodInfo);
else
_setter = (Action<T>)Delegate.CreateDelegate(typeof(Action<T>), targetObject, methodInfo);
return new TargetInfo(methodInfo, targetObject);
}
The expression (_propertyExpression) is always of a property. And the property always has a setter.
I need to extract the property's setter as Action (which I can do
no problem)
I also need the instance of the object containing this
property without using Compile() as it is not available on some of
the target platforms I am targeting.
The reason I need the instance is to determine whether or not another object instance of my class is currently utilizing that property SETTER on THAT object. (No Threading, just usage over a span of time) I store the object Instance and property setter info together as a key, if two keys that are equal that exist then there is a conflict and it is handled based on the user's configuration settings of my class.
I am able to get the object instance for simple expressions like:
() => MyProperty
or
() => MyObjectInst.PropertyFoo
or
() => MyStaticClass.PropertyFooBar
No Sweat!
But what if the user does this:
//Need instance of 'someObject' here.
() => SomeArray[idx].someObject.propertyA
or blow my top:
//Need instance of 'someField[4]' here
() => SomeStaticClass.somePropertyList[5].SomeDictionary[objKey].SomeProperty.someFieldArray[4].propertyB
AAAK!
I've been looking at this for a while and I BELIEVE that I need to traverse the tree BACK to the base object (ConstantExpression) then start evaluating back UP the tree using the info collected walking to the front. Given the examples above I decided that I need "bigger guns".
Is there an easier way to get the property's caller's instance other than completely walking the tree WITHOUT using Compile()? Please explain if so!
If not 1. If anyone could point me in the right direction on how to traverse the tree and handle stuff like the above. That would be great. I'm not finding a whole lot of info on traversing Expression Trees, expression types, etc. Even a reference to a recommended book specific to the subject would be helpful.
sigh Should I just give up and force the user to use simple expressions.
ie. Do not allow the user to type in lengthy property access lines.
Clarification:
The setter is being cached for use by a mechanism class "FOO" that will be setting this value an UNKNOWN range of values of type T over some defined period of time. The object instance is cached and used as a key to detect the case that another instance of FOO tries to attach and set values to the same property on that same object. The object instance is used to detect these conflicts and also to keep track of all of the "FOO"s attached to any particular object. The user can attach multiple "FOO"s to the same object, to different properties. In the case that the user attaches an instance of FOO to a property on an object that already has a FOO attached for that property, a conflict event occurs. FOO can be configured on how to handle when that happens.
Here's the problems with your suggested approaches:
Is there an easier way to get the property's caller's instance other
than completely walking the tree WITHOUT using Compile()? Please
explain if so!
Short answer, no. Expressions are meant to be compiled. Either into .NET Funcs/Actions or some other platform (LINQ-to-Entities essentially compiles them into SQL). If you don't want to compile it, you're probably using the wrong tool.
If not 1. If anyone could point me in the right direction on how to
traverse the tree and handle stuff like the above. That would be
great. I'm not finding a whole lot of info on traversing Expression
Trees, expression types, etc. Even a reference to a recommended book
specific to the subject would be helpful.
The best way to traverse an Expression tree is by inheriting from ExpressionVisitor. A good blog to start with would be Matt Warren's blog http://blogs.msdn.com/b/mattwar/, read the series on implementing IQueryable. But no, it's not easy.
One could (theoretically) inherit from ExpressionVisitor to walk down/up the chain to the original instance. But you would then have to walk back up/down the chain somehow, and the easiest way to do that would be by compiling the child Expressions. You could, theoretically, use Reflection to walk back, as your answer tries, but I hope you're distinctly getting the impression you have chosen the wrong tool if your No-Compiling stance is iron-clad.
sigh Should I just give up and force the user to use simple expressions.
You haven't outlined the benefits/drawbacks of this.
I have confirmed that the below works on for MONO -> iOS... At least with the basics and arrays. Haven't been able to get the Dictionary/List rolling. It seems AOT doesn't like MethodInfo.Invoke.
EDIT:
I found this answer on MSDN:
https://social.msdn.microsoft.com/Forums/vstudio/en-US/af305a45-36e4-4607-9190-f1b33a0bea57/get-class-instance-from-lambda-expression
It traverses the Expression tree, evaluating each part of the tree as necessary and finally returns the containing object of the property specified.
Put in this (along with adding the method code below in):
targetObject = GetContainer(_propertyExpression);
instead of this:
targetObject = Expression.Lambda<Func<object>>(bodyExp).Compile()();
in the code above.
I have yet to do full testing on it on other platforms and I'm sure I'll run into other cases where I need to add more cases but this might be enough to help someone else and enough to keep me going and I'll try and keep this updated as I run into more:
public static object GetContainer<T>(Expression<Func<T>> propertyLambdaExpression)
{
return Evaluate((propertyLambdaExpression.Body as MemberExpression).Expression);
}
public static object Evaluate(Expression e)
{
switch (e.NodeType)
{
case ExpressionType.Constant:
return (e as ConstantExpression).Value;
case ExpressionType.MemberAccess:
{
var propertyExpression = e as MemberExpression;
var field = propertyExpression.Member as FieldInfo;
var property = propertyExpression.Member as PropertyInfo;
var container = propertyExpression.Expression == null ? null : Evaluate(propertyExpression.Expression);
if (field != null)
return field.GetValue(container);
else if (property != null)
return property.GetValue(container, null);
else
return null;
}
case ExpressionType.ArrayIndex: //Arrays
{
var arrayIndex = e as BinaryExpression;
var idx = (int)Evaluate(arrayIndex.Right);
var array = (object[])Evaluate(arrayIndex.Left);
return array[idx];
}
case ExpressionType.Call: //Generic Lists and Dictionaries
{
var call = e as MethodCallExpression;
var callingObj = Evaluate(call.Object);
object[] args = new object[call.Arguments.Count];
for (var idx = 0; idx < call.Arguments.Count; ++idx)
args[idx] = Evaluate(call.Arguments[idx]);
return call.Method.Invoke(callingObj, args);
}
default:
return null;
}
}

How can I access the value of the target of a Func<Client, bool>?

I have C# a method that is declared as the following:
public IEnumerable<ClientEntity> Search(Func<Client, bool> searchPredicate)
{
// Uses the search searchPredicate to perform a search.
}
This method gets called with something like:
string searchCriteria = "My Search Criteria";
bool searchOnlyActive = false;
myClientService.Search(c => c.Name.Contains(searchCriteria) && (c.Active || !searchOnlyActive));
Now, if I throw a breakpoint at the beginning of that method and I look at the searchPredicate properties in the Immediate Window, when I type searchPredicate.Target, I get something like this:
{MyNamespace.ClientsService.}
searchCriteria: "My Search Criteria"
searchOnlyActive: false
What I would like is to actually get the "My Search Criteria" value and the false value displayed there, like the debugger does, but I didn't manage to as the type of the Target property is something like "<>c__DisplayClass2" which I have no idea where that came from. I know it can be done because the debugger does it, I just don't know how.
Any ideas? Thanks!
<>c__DisplayClass2 is the class that the compiler invented to get the capture context. You can just use reflection:
object target = searchPredicate.Target;
if(target != null) {
foreach(var field in target.GetType().GetFields()) {
Console.WriteLine("{0}={1}", field.Name, field.GetValue(target));
}
}
which outputs:
searchCriteria=My Search Criteria
searchOnlyActive=False
However! Unless you understand anonymous methods and captured variables (and how that is implemented in terms of compiler-generated context classes), I don't think this will do what you want it to; for example, there could be no context (a Target that is null), or multiple nested contexts...
Also: expression trees via Expression<Func<Client,bool>> are far more inspectable, if that is your intent.

How do you dynamially invoke a property, but only if its argument is a certain type?

I am trying to use reflection to get all the (settable) properties in my POCO (which take a string argument, for now, but I plan to expand to other types), and set them to something arbitrary. (I need to make sure the .Equals method is implemented properly.)
I have some code in my unit tests that looks something like this (where t is the object under test, and u is a default version of that object):
foreach(var property in t.GetType().GetProperties())
{
var setMethod = property.GetSetMethod();
var type = setMethod.GetParameters()[0].GetType();
if(typeof(string).IsAssignableFrom(type))
{
setMethod.Invoke(t, new object[] {"a"});
Assert.IsFalse(t.Equals(u));
Assert.IsFalse(t.GetHashCode() == u.GetHashCode());
}
}
The place where this fails is where I say typeof(string).IsAssignableFrom(type). The code inside the if { ... } block never runs. How would I properly code up this part of the test?
You have confused ParameterInfo.GetType() with ParameterInfo.ParameterType. You should have:
var type = setMethod.GetParameters()[0].ParameterType;
.GetType() returns the Type of the current object, in this case ParameterInfo, which is obviously not what you want.

Categories