How to dynamically assign lambda<expression<delegate>> to expression<delegate> - c#

I am trying to make dynamic expression and assign lambda to it. As a result, I got exception:
System.ArgumentException: Expression of type 'Test.ItsTrue' cannot be used for assignment to type 'System.Linq.Expressions.Expression`1[Test.ItsTrue]'
What is wrong?
public delegate bool ItsTrue();
public class Sample
{
public Expression<ItsTrue> ItsTrue { get; set; }
}
[TestClass]
public class MyTest
{
[TestMethod]
public void TestPropertySetWithExpressionOfDelegate()
{
Expression<ItsTrue> itsTrue = () => true;
// this works at compile time
new Sample().ItsTrue = itsTrue;
// this does not work ad runtime
var new_ = Expression.New(typeof (Sample));
var result = Expression.Assign(
Expression.Property(new_, typeof (Sample).GetProperties()[0]),
itsTrue);
}
}

The second argument of Expression.Assign is the expression representing the value to assign. So currently you're effectively trying to assign an ItsTrue to the property. You need to wrap it so that it's an expression returning the value itsTrue... either via Expression.Quote or Expression.Constant. For example:
var result = Expression.Assign(
Expression.Property(new_, typeof (Sample).GetProperties()[0]),
Expression.Constant(itsTrue, typeof(Expression<ItsTrue>)));
Alternatively, you might want Expression.Quote - it really depends on what you're trying to achieve.

Related

How do you create an Expression of an enum from its type and the name of one of its fields?

Had a hard time finding what I'm trying to do and this post was the closest I could find. This post won't work as I don't know the integer value of the enum, I only know its name. Given the following code:
public enum Foo
{
Row = 0,
Column = 20, // This is why the second post won't work, I only know the name "Column"
None = 30
}
public static class ExpressionGetter
{
public static Expression GetExpression(Type type, string name)
{
// Not sure what I should do here. I want an expression object for Foo.Row
}
}
void Main()
{
var expression = ExpressGetter.GetExpression(typeof(Foo), "Row");
}
Later in my application, I am building expression trees to generate LINQ queries and I know the type of the enum and name of the enum and now I want to create an Expression.Constant of it or if there's another way to do this, I'd like to know how.
I want at the end an expression that looks like this:
Foo.Row
I've tried:
Expression.Property(null, enumType, name)
But it does not work. Results in
ArgumentException: Property 'Row' is not defined for type 'Foo'
Parameter name: propertyName
which makes sense because it's a struct not an object.
So I'm not sure how to build the Expression Foo.Row given the enum type Foo and the name as a string.
An enum value is a static field of the enum type. If you only have the name of the enum value as a string, the second version is what you're looking for. But you could also do Enum.Parse() with the first version.
Expression.Constant(Foo.Row, typeof(Foo));
// Or any other string that's valid
var name = "Row";
MemberExpression.Field(null, typeof(Foo), name);
More or less like this:
public enum EnumerationTest
{
A, B, C
}
public class ClassTest
{
public EnumerationTest Test { get; set; }
}
public static Expression PropertyExpression()
{
// Think of this like a lambda (p) => p.Test == Enumeration.A
var parameter = Expression.Parameter(typeof(ClassTest), "p");
var property = Expression.PropertyOrField(parameter, "Test");
var value = (EnumerationTest)Enum.Parse(typeof(EnumerationTest), "A");
var constant = Expression.Constant(value, typeof(EnumerationTest));
return Expression.Equal(property, constant);
}
You generally are using a lot of reflection and string parsing when doing Expression trees. At least that's what I have found in my experience

How to expect property type of a class as parameter in a generic function?

For the sake of simplicity take following example, which is not valid in C#:
public void SomeGenericFunc<T>(T classObject, T.Property.Type classPorpertyType)
{
string propertyName = nameof(classPropertyType);
// ...
}
Sample simple class:
public class Car
{
public Car(){}
public int DoorsCount { get; set; }
public string Color { get; set; }
}
A function call would look something like this:
SomeGenericFunc<Car>(new Car(), Car.DoorsCount); //should be valid
SomeGenericFunc<Car>(new Car(), SomeType); //should be invalid at compile time: SomeType is not a property of Car
SomeGenericFunc<Car>(new Car(), Car.Color); //should be valid
Obviously there is nothing like T.Property.Type available in C#. In this example i don't want to pass nameof(Car.DoorsCount) everytime i call the function. I want the nameof() call to take place in SomeGenericFunc<T>(),so i can call SomeGenericFunc<T>() with any class and any of that class' property.
So is it possible to pass and expect a property type of a class in a generic function?
EDIT:
To make it clear: I DON'T want the value of the property Car.DoorsCount. I want the name of the property, without passing it directly as parameter. I want to resolve the name of the property in SomeGenericFunc<T>().
Try using expression trees:
static void GetPropertyName<T, TProperty>(Expression<Func<T, TProperty>> property) {
var propertyInfo = (property.Body as MemberExpression).Member;
Console.WriteLine(propertyInfo.Name);
}
You can call it like this:
GetPropertyName((Car c) => c.DoorsCount);
Obviously, this will throw an exception if you try to pass in stuff that isn't a member expression.
You can't use nameof here because nameof is a constant expression. The expression in the brackets is not evaluated. The whole nameof expression is evaluated at compile time. This means that trying to get the name of the property passed as a parameter will just get you the name of the parameter. You need something that works at runtime, like expression trees.
Also note that you don't need an instance of Car here. What the method needs is just an expression. No property's value is actually evaluated.
Your proposal has no solution after all: you don't want to pass the name of a given property using nameof and you want to give a property to later get the whole type to get property type.
If you're looking to both receive property value and get the its name later, you may use an expression tree:
public class A
{
public int Value { get; set; }
}
public static S DoStuff<T, S>(T some, Expression<Func<T, S>> propertySelector)
{
if(selector.Body is MemberExpression memberExpr)
{
var propertyType = memberExpr.Member;
var propertyName = propertyType.Name;
// Extra: as per your last edit, you don't want this, but
// I leave the code so you're aware that you can have both
// the property and its value
var somePropertyValue = propertySelector.Compile()(some);
return somePropertyValue;
}
else
throw new ArgumentException("propertySelector", "This isn't a member expression");
}
So, you would call that method as follows:
DoStuff(new A(), a => a.Value);
Trying to stay as close as possible to given code sample while providing minimal error handling:
public static void SomeGenericFunc<T, PT>(T classObject, Expression<Func<T, PT>> expression)
{
var targetType = typeof(T);
var property = expression.Body as MemberExpression;
var propertyInfo = property?.Member as PropertyInfo;
if (property == null || propertyInfo == null)
throw new ArgumentException("Expecting property!");
if (propertyInfo.ReflectedType != targetType)
throw new ArgumentException($"Property does not belong to type {targetType.Name}");
string propertyName = propertyInfo.Name;
}
You can call it with:
SomeGenericFunc(new Car(), car => car.DoorsCount);

How to pass lambda Expression from one function to other function as parameter?

I have following class (some part is copied from here):
class TestExpression
{
public string GetValue(Expression<Func<object>> field)
{
string str = GetColumnName(field);
//Do something with 'str'
return str;//Return modified 'str'
}
public string GetColumnName<TType>(Expression<Func<TType>> field)
{
var me = field.Body as MemberExpression;
if(me == null)
{
throw new ArgumentException("You must pass a lambda of the form: '() => Class.Property' or '() => object.Property'");
}
return me.Member.Name;
}
}
public sealed class MyClass
{
public static int StaticProperty { get; set; }
public int InstanceProperty { get; set; }
}
Following is the way I use above class:
TestExpression te = new TestExpression();
string name;
name = te.GetColumnName(() => MyClass.StaticProperty);//Works correctly
name = te.GetColumnName(() => new MyClass().InstanceProperty);//Works correctly
name = te.GetValue(() => MyClass.StaticProperty);//Fail
name = te.GetValue(() => new MyClass().InstanceProperty);//Fail
So, if I call the GetColumnName() function directly, it works all great. But, I need to use this logic at multiple locations, that is why I put it in separate function and call from other functions (like GetValue()). In that case, it does not work. In that case, field.Body as MemberExpression evaluates to null.
I do not want to expose GetColumnName() as public; it will be private function.
How to pass lambda from one function to other function as parameter?
The problem is that your C# code actually includes a type-cast, which you don't see because in the C#, but does happen on the Expression since the expected type is Expression<Func<object>> (note the object!).
() => MyClass.StaticProperty
is actually:
() => (object)MyClass.StaticProperty
The (object) part converts to Convert(MyClass.StaticProperty). The suddenly this isn't a MemberExpression any more, it is a UnaryExpression.
You can prevent all this by making the method generic, thus avoiding the required cast to object:
public string GetValue<TType>(Expression<Func<TType>> field)
Change the signature of the GetValue method to:
public string GetValue<T>(Expression<Func<T>> field)
Otherwise you are operating on the object where your properties are not visible.

Untyped lambda calculus in C#

I've been trying to implement raw lambda calculus on C# but I am having some troubles implementing it, as in the end, I am always asked for objects.
I would like something that would allow me, for instance, to define a few basic logical combinators, such as
I = Lambda x. x
M = Lambda x. x(x)
but C# seems to run on the assumption that it will get an object in the end. I've tried to define them in various ways, such as
using lambda = Func<Object, Object>;
using lambda = Func<Func<Object, Object>, Func<Object, Object>>;
using lambda = Func<Func, Func>;
and so on, but either those do not obey the syntax or are incompatible with
lambda I = x => x;
lambda M = x => x(x);
I tried using the delegate
public delegate object lambda(Object o);
static object i(object o)
{
return o;
}
static object m(object o)
{
return ((lambda)o)(o);
}
But in the end, any actual use of those functions will still require an argument at the end of the line, and a dummy argument like
m(m(i('')));
will simply lead to a cast error during execution.
Is there a way to implement typeless lambda calculus natively, or do I have to go back to string processing?
For an example of execution of the program, it would look something like this. For the following functions :
lambda i(lambda x)
{
print("i");
return x;
}
lambda m(lambda x)
{
print("m");
return x(x);
}
The execution of (m(m))(i) should be something like m(m) is evaluated, returning m(m) after printing "m", which gives us back the original (m(m))(i), which will then print an infinite amount of "m" (this is the simplest infinite loop with logical combinators, although this will involve some trampolining later on to avoid blowing the stack).
Rather than encoding a lambda expression as Func<,> (which is probably not a good match for untyped lambda calculus), you should encode it as an abstract syntax tree. Something like this:
public class LambdaAbstraction: ILambdaExpression {
public LambdaVariable Variable { get; set; }
public ILambdaExpression Body { get; set; }
}
public class LambdaApplication: ILambdaExpression {
public ILambdaExpression Function { get; set; }
public ILambdaExpression Argument { get; set; }
}
public class LambdaVariable: ILambdaExpression {
public string Name { get; set; }
}
For example, M would be
ILambdaExpression M = new LambdaAbstraction {
Variable = new LambdaVariable { Name = "x" },
Body = new LambdaApplication {
Function = new LambdaVariable { Name = "x" },
Argument = new LambdaVariable { Name = "x" }
}
}
Then it's quite straightforward to implement recursive methods for alpha renaming and beta reductions on this data structure.

Why does this method keep returning dynamic despite the return type in the signature?

So the type being returned by the activator (not shown here) is just a POCO that I created. Nothing special about it at all. But despite, the return type of GetWrapper or GetWrapper<T> the object being returned is of type dynamic so none of the properties of the actual class being return are being seen by intellisense. Any ideas?
UPDATE:
Sorry, Jon:
public static T GetWrapper<T>(object type, dynamic obj)
where T : class, IRedditObject
{
return GetWrapper(type, obj) as T;
}
public static object GetWrapper(object type, dynamic obj)
{
return Activator.CreateInstance(Types[type.ToString()], obj);
}
public class LinkWrapper : IRedditObject
{
private readonly dynamic _link;
public string Kind { get { return "t3"; } }
public dynamic Data { get { return _link.data; } }
public LinkWrapper(dynamic link)
{
_link = link;
}
public string Domain { get { return Data.domain; } }
}
[TestMethod]
public void Test()
{
var proxy = new SubredditProxy();
var dotnet = proxy.GetSubredditAsync("dotnet").Result;
var child1 = dotnet.data.children[0];
// this is being returned as dynamic
var obj = RedditDynamicObjectWrapperFactory.GetWrapper<LinkWrapper>(child1.kind, child1);
Assert.IsNotNull(obj);
}
I strongly suspect that either child1 or child1.kind are of type dynamic, meaning that the expression is deemed to be a dynamically-bound expression, despite everything else.
Here's a short but complete example to demonstrate what I mean:
using System;
class Test
{
public static T Foo<T>(object x)
{
return default(T);
}
public static void Main(string[] args)
{
object a = new object();
dynamic b = a;
var c = Foo<string>(a);
var d = Foo<string>(b);
Console.WriteLine(c.SomeRandomMember); // Invalid
Console.WriteLine(d.SomeRandomMember); // Valid
}
}
The invalid statement is invalid because the type of c is string - but the subsequent statement is fine, because the type of d is dynamic.
Even though there's only one possible method which it could be bound to at execution time - and even though that binding will always work - the basic rule is that almost any expression involving a dynamic value is deemed to be of type dynamic. (There are a few exceptions such as as and new.)
To make your return value non-dynamic, just cast your values to object:
var obj = RedditDynamicObjectWrapperFactory.GetWrapper<LinkWrapper>
((object) child1.kind, (object) child1);
That will now be a statically bound call. Or you could leave it as a dynamically bound call, and use the implicit conversion from an expression of type dynamic to other types:
LinkWrapper obj = RedditDynamicObjectWrapperFactory.GetWrapper<LinkWrapper>(child1.kind, child1);
I agree with the current answer (https://stackoverflow.com/a/25586620/1942762) but here is the explanation from the the C# programming guide (Overload resolution with arguments of type dynamic):
Overload resolution occurs at run time instead of at compile time if one or more of the arguments in a method call have the type dynamic, or if the receiver of the method call is of type dynamic.
Your parameter is probably of type dynamic so your IDE will consider obj as a dynamic too

Categories

Resources