expression trees linq get value of a parameter? - c#

AddOptional<tblObject>(x =>x.Title, objectToSend.SupplementaryData);
private static void AddOptional<TType>(Expression<Func<TType,string>> expr, Dictionary<string, string> dictionary)
{
string propertyName;
string propertyValue;
Expression expression = (Expression)expr;
while (expression.NodeType == ExpressionType.Lambda)
{
expression = ((LambdaExpression)expression).Body;
}
}
In Above code i would like to get actual value of property title, not ony propert name , is it possible ?

private static void Main(string[] args)
{
CompileAndGetValue<tblObject>(x => x.Title, new tblObject() { Title = "test" });
}
private static void CompileAndGetValue<TType>(
Expression<Func<TType, string>> expr,
TType obj)
{
// you can still get name here
Func<TType, string> func = expr.Compile();
string propretyValue = func(obj);
Console.WriteLine(propretyValue);
}
However, you must be aware that this can be quite slow. You should measure how it performs in your case.
If you don't like to pass your object:
private static void Main(string[] args)
{
var yourObject = new tblObject {Title = "test"};
CompileAndGetValue(() => yourObject.Title);
}
private static void CompileAndGetValue(
Expression<Func<string>> expr)
{
// you can still get name here
var func = expr.Compile();
string propretyValue = func();
Console.WriteLine(propretyValue);
}

Related

Custom where can't run

class Program
{
private delegate Boolean SomeDelegate(string value);
static void Main(string[] args)
{
var data = new List<string>() { "bill", "david", "john", "daviddd" };
SomeDelegate AA = A;
var test2 = data.DoWhere(AA); //This Line Compile is wrong
}
public static bool A(string value)
{
if (value.StartsWith("d"))
{
return true;
}
return false;
}
}
public static class CustomClass
{
public static IEnumerable<T> DoWhere<T>(this IEnumerable<T> source, Func<T, Boolean> predicate)
{
foreach (T item in source)
{
if (predicate.Invoke(item))
{
yield return item;
}
}
}
}
I want to custom method and condition what data I need. But this code Compile is wrong in var test2 = data.DoWhere(AA);
cannot convert from 'SomeDelegate' to 'System.Func<string, bool>'
And I don't know How to fix it. Please review my code.
SomeDelegate(AA) is not Func<string, bool>. It should simply be a DoWhere(A) in your code. ie:
class Program
{
static void Main(string[] args)
{
var data = new List<string>() { "bill", "david", "john", "daviddd" };
var test2 = data.DoWhere(A); //This Line Compile is wrong
}
public static bool A(string value)
{
if (value.StartsWith("d"))
{
return true;
}
return false;
}
}
A simpler way to write it:
class Program
{
static void Main(string[] args)
{
var data = new List<string>() { "bill", "david", "john", "daviddd" };
Func<string, bool> A = value => value.StartsWith("d");
var test2 = data.DoWhere(A);
}
}
Note: Such a function should check if the value is null.
You can't cast an instance of SomeDelegate to a Func<string, bool>:
var test2 = data.DoWhere(AA); //This Line Compile is wrong
Try this instead:
var test2 = data.DoWhere(c => AA(c));
Or use Invoke:
var test2 = data.DoWhere(AA.Invoke);
Or use a method with same signature like A:
var test2 = data.DoWhere(A);
you said in a comment
I just want to custom my own condition method
so code can be much easier of the one you wrote:
public class Program
{
public static void Main(string[] args)
{
var data = new List<string>() { "bill", "david", "john", "daviddd" };
var stringsStartingWithD = data.Where (s => StarstWithD(s)).ToList();
var anotherOne = data.Where (s => SomeOtherTest(s)).ToList();
}
public static bool StarstWithD(string str)
{
if (str.StartsWith("d"))
{
return true;
}
return false;
}
public static bool SomeOtherTest(string str)
{
bool result = false;
// apply desired logic and return true/false
//...
return result;
}
}
For a simple test as the one you are using, you can also avoid creating the StartsWithDmethod and simply use something like this:
public class Program
{
public static void Main(string[] args)
{
var data = new List<string>() { "bill", "david", "john", "daviddd" };
var stringsStartingWithD = data.Where (s => s.StartsWith("d")).ToList();
}
Your entire code is just two lines now

Create Expression Tree dynamically

I had an idea and want to know if it can work.
I have a simple classes with properties and want to generate accessors with Expressions.
But in the end I need to get a Func<Test, string> but I don't know the types when I use them.
A small example
class Program
{
static void Main(string[] args)
{
Test test = new Test();
test.TestString = "Blubb";
var actionStub = typeof(Helper).GetMethod("CreatePropertyGetter").MakeGenericMethod(new Type[] { test.GetType(), typeof(string)});
dynamic action = actionStub.Invoke(null, new object[] {test.GetType(), "TestString"});
var x = action(test);
}
}
public class Test
{
public string TestString { get; set; }
}
public static class Helper
{
public static Func<TType, TPropValueType> CreatePropertyGetter<TType, TPropValueType>(Type type,
string propertyName)
{
PropertyInfo fieldInfo = type.GetProperty(propertyName);
ParameterExpression targetExp = Expression.Parameter(typeof(TType), "target");
MemberExpression fieldExp = Expression.Property(targetExp, fieldInfo);
UnaryExpression assignExp = Expression.Convert(fieldExp, typeof(TPropValueType));
Func<TType, TPropValueType> getter =
Expression.Lambda<Func<TType, TPropValueType>>(assignExp, targetExp).Compile();
return getter;
}
}
The problem is I cant call the expression without dynamic, because I cant simple cast it to Func<object, object>
You're generating (TType target) => target.Something. Instead, generate (object target) => (object)((TType)target).Something so that you can use Func<object, object>.
It's not clear what exactly you are asking for, but here is an example how you can make it Func<object, object>:
public static class Helper
{
public static Func<object, object> CreatePropertyGetter(Type type, string propertyName)
{
var fieldInfo = type.GetProperty(propertyName);
var targetExp = Expression.Parameter(typeof(object), "target");
var fieldExp = Expression.Property(Expression.ConvertChecked(targetExp, type), fieldInfo);
var getter = Expression.Lambda<Func<object, object>>(fieldExp,targetExp).Compile();
return getter;
}
}

How can i convert Func<T,object> to PropertyInfo

I need property name to be extracted form Func please help me if its possible. Thanks.
public void Converter<T>(Func<T,Ojbect> F)
{
}
public class Tester
{
void main()
{
String Name = Converter<User>(m=>m.Id);
//Name should be equal to "Id"
}
}
What you need is:
public static string GetPropertyName<T>(Expression<Func<T>> property)
{
var memberExpress = property.Body as MemberExpression;
return memberExpress.Member.Name;
}
Which you can then call using:
var user = new User();
string name = GetPropertyName(() => user.Name);
Or even:
public static string GetPropertyName<T, TValue>(Expression<Func<T, TValue>> property)
{
var memberExpress = property.Body as MemberExpression;
return memberExpress.Member.Name;
}
Which you can call using:
string name = GetPropertyName<User, string>(u => u.Id);

How to create delegate of Func<a,b> when a's method has parameters

I am trying to call a method that takes in a function, but using relection. I've gotten it to work when the method is parameterless but I can't figure out how to invoke it when there are arguments. This is a contrived simplified example, but this boils down the problem. I will not know the arguments to Add until runtime.
Any pointers? Do I have to use expression trees? Is there an easier way to do this?
public void Main()
{
//works
CallFunction(typeof (Processor), "Count");
//I don't understand what I need to modify to make add work
CallFunction(typeof (Processor), "Add");
}
public void CallFunction(Type type, string methodToCall)
{
var targetMethod = type.GetMethod(methodToCall);
var constructedType = typeof (MethodCaller<>).MakeGenericType(type);
dynamic target = Activator.CreateInstance(constructedType);
var method = constructedType.GetMethod("Do").MakeGenericMethod(targetMethod.ReturnType);
var func = typeof (Func<,>).MakeGenericType(type, targetMethod.ReturnType);
var toCall = Delegate.CreateDelegate(func, targetMethod);
method.Invoke(target, new object[] { toCall });
}
public class Processor
{
public int Count()
{
return 1;
}
public int Add(int toAdd)
{
return 1 + toAdd;
}
}
public class MethodCaller<TParm> where TParm : new()
{
public TResult Do<TResult>(Func<TParm, TResult> func)
{
return func(new TParm());
}
}
Like type.InvokeMember(method_name, System.Reflection.BindingFlags.InvokeMethod, null, type_instance, new object[] { param1, param2, param3 }); ?
https://msdn.microsoft.com/en-us/library/66btctbe(v=vs.110).aspx
Actually whole CallFunction method can be simplified like this:
public void CallFunction(Type type, string methodToCall, params object[] args)
{
// Why this part is so complex? Do I miss something?
//var constructedType = typeof (MethodCaller<>).MakeGenericType(type);
//dynamic target = Activator.CreateInstance(constructedType);
var target = Activator.CreateInstance(type);
var result = type.InvokeMember(method_name, System.Reflection.BindingFlags.InvokeMethod, null, target, args);
// ... do something with result if you need ...
}
If you need MethodCaller.Do, but can sacrifice types on signature (or some performance on boxing/unboxing for DoTyped)
public void CallFunction(Type type, string methodToCall, params object[] args)
{
var delegate_wrapper = new Func<object, object>(
instance => type.InvokeMember(methodToCall, BindingFlags.InvokeMethod, null, instance, args)
);
var target_method = type.GetMethod(methodToCall);
var mc_custom_type = typeof (MethodCaller<>).MakeGenericType(type);
var mc_instance = Activator.CreateInstance(mc_custom_type);
var mc_custom_method = mc_custom_type.GetMethod("Do").MakeGenericMethod(target_method.ReturnType);
mc_custom_method.Invoke(mc_instance, new object[] { delegate_wrapper });
}
public class MethodCaller<TParm> where TParm : new()
{
public TResult DoTyped<TResult>(Func<TParm, TResult> func)
{
return Do<TResult>(oinstance=>func((TParm)oinstance));
}
public TResult Do<TResult>(Func<object, object> func)
{
Console.WriteLine("I AM DO");
return (TResult)func(new TParm());
}
}
Have you tried looking at Impromptu framework. It is primarily for duck typing but the library provide rather slick api to access methods and pass arguments.
https://github.com/ekonbenefits/impromptu-interface/wiki/UsageReallyLateBinding

Get the parameter value from a Linq Expression

I have the following class
public class MyClass
{
public bool Delete(Product product)
{
// some code.
}
}
Now I have a helper class that looks like this
public class Helper<T, TResult>
{
public Type Type;
public string Method;
public Type[] ArgTypes;
public object[] ArgValues;
public Helper(Expression<Func<T, TResult>> expression)
{
var body = (System.Linq.Expressions.MethodCallExpression)expression.Body;
this.Type = typeof(T);
this.Method = body.Method.Name;
this.ArgTypes = body.Arguments.Select(x => x.Type).ToArray();
this.ArgValues = ???
}
}
The idea ist to use this code from somewhere:
// I am returning a helper somewhere
public Helper<T> GetMethod<T>()
{
var product = GetProduct(1);
return new Helper<MyClass>(x => x.Delete(product));
}
// some other class decides, when to execute the helper
// Invoker already exists and is responsible for executing the method
// that is the main reason I don't just comile and execute my Expression
public bool ExecuteMethod<T>(Helper<T> helper)
{
var instance = new MyClass();
var Invoker = new Invoker(helper.Type, helper.Method, helper.ArgTypes, helper.ArgValues);
return (bool)Invoker.Invoke(instance);
}
The point where I am stuck is how to extract the arguments from the expression itself.
I found this way
((ConstantExpression)((MemberExpression)body.Arguments[0]).Expression).Value
which seems to be an object type with a field "product" but I believe there must be a simpler solution.
Any suggestions.
Update
Just to clarify, I modified my code according to what I want to achive. In my real word application I already have a class that does the same but without an expression tree:
var helper = new Helper(typeof(MyClass), "Delete",
new Type[] { typeof(Product) }, new object[] {product}));
The main reason for my Helper<T> is to have Compile-Time checking if the method signature is valid.
Update 2
This is my current implementation, is there a better way to acces the values, without using reflection?
public Helper(Expression<Func<T, TResult>> expression)
{
var body = (System.Linq.Expressions.MethodCallExpression)expression.Body;
this.Type = typeof(T);
this.Method = body.Method.Name;
this.ArgTypes = body.Arguments.Select(x => x.Type).ToArray();
var values = new List<object>();
foreach(var arg in body.Arguments)
{
values.Add(
(((ConstantExpression)exp.Expression).Value).GetType()
.GetField(exp.Member.Name)
.GetValue(((ConstantExpression)exp.Expression).Value);
);
}
this.ArgValues = values.ToArray();
}
This method works pretty well. It returns the argument types and values for an Expression>
private static KeyValuePair<Type, object>[] ResolveArgs<T>(Expression<Func<T, object>> expression)
{
var body = (System.Linq.Expressions.MethodCallExpression)expression.Body;
var values = new List<KeyValuePair<Type, object>>();
foreach (var argument in body.Arguments)
{
var exp = ResolveMemberExpression(argument);
var type = argument.Type;
var value = GetValue(exp);
values.Add(new KeyValuePair<Type, object>(type, value));
}
return values.ToArray();
}
public static MemberExpression ResolveMemberExpression(Expression expression)
{
if (expression is MemberExpression)
{
return (MemberExpression)expression;
}
else if (expression is UnaryExpression)
{
// if casting is involved, Expression is not x => x.FieldName but x => Convert(x.Fieldname)
return (MemberExpression)((UnaryExpression)expression).Operand;
}
else
{
throw new NotSupportedException(expression.ToString());
}
}
private static object GetValue(MemberExpression exp)
{
// expression is ConstantExpression or FieldExpression
if (exp.Expression is ConstantExpression)
{
return (((ConstantExpression)exp.Expression).Value)
.GetType()
.GetField(exp.Member.Name)
.GetValue(((ConstantExpression)exp.Expression).Value);
}
else if (exp.Expression is MemberExpression)
{
return GetValue((MemberExpression)exp.Expression);
}
else
{
throw new NotImplementedException();
}
}
You can compile the argument expression and then invoke it to calculate the value:
var values = new List<object>();
foreach(var arg in body.Arguments)
{
var value = Expression.Lambda(argument).Compile().DynamicInvoke();
values.Add(value);
}
this.ArgValues = values.ToArray();
Here is an example of creation of a delegate using a lambda. The object instance is encapsulated into the delegate using a C# feature called closure.
MyClass instance = new MyClass();
//This following line cannot be changed to var declaration
//since C# can't infer the type.
Func<Product, bool> deleteDelegate = p => instance.Delete(p);
Product product = new Product();
bool deleted = deleteDelegate(product);
Alternatively you are trying to create a Helper that automagically Currys.
public class Helper<T>
where T : new()
{
public TResult Execute<TResult>(Func<T, TResult> methodLambda)
{
var instance = new T();
return methodLamda(instance);
}
}
public void Main()
{
var helper = new Helper<MyClass>();
var product = new Product();
helper.Execute(x => x.Delete(product));
}
However I have to say this problem looks suspiciously like the creation of a Helper class to handle the lifetime of a WCF proxy....You know...just say...in which case this ISN'T how I would approach this...simply because this approach leaks WCF specific code into your domain.

Categories

Resources