I have a specific object in C#, call it MyCustomObject. MyCustomObject is of type MyNamespace.CustomObject, and every object of that type contains a method MyCustomMethod. I am trying to get the MethodInfo (System.Reflection.MethodInfo) of MyCustomObject.MyCustomMethod so I can use it to create an expression tree later. However, if I just use typeof(MyCustomObject).GetMethod("MyMethodInfo"), it returns a general method for all objects of type MyNamespace.CustomObject. How can I get the MethodInfo of just MyCustomObject.MyCustomMethod?
When creating your expression tree (per this comment), you presumably want to use the Call factory method.
In your case, you're trying to create an expression tree representing an instance method call, not a static method call; the difference between them is that an instance method call uses an instance, while a static method call does not.
To create such an expression tree, you'll need some kind of expression tree that represents the instance; it might be a property or field, or the result of another method call. But if you want to apply it to an existing instance, you could pass your instance into the Constant factory method.
You could pass this node into one of the Call overloads which represent an instance method call, such as this one, for an instance method call with no arguments.
Something like this:
// using System.Linq.Expressions.Expression
CustomObject MyCustomObject = /* initialized somehow */
var methodInfo = typeof(CustomObject).GetMethod("MyCustomMethod");
var expr = Lambda(
Call(
Constant(MyCustomObject),
methodInfo
),
new ParameterExpression[] { } // if the LambdaExpression has parameters, add them here
);
Addendum
When using the compiler to generate a similar expression tree:
CustomObject MyCustomObject = /* initialized somehow */
Expression<Action> expr = () => MyCustomObject.MyCustomMethod();
MyCustomObject isn't represented with a ConstantExpression, but rather with a MemberAccessExpression. The C# compiler rewrites closed-over variables (in this case, MyCustomObject within the lambda expression) as a property access on a compiler-generated object. Instead of the call to Constant, the corresponding factory methods to represent MyCustomObject would look something like this:
// using System.Linq.Expressions.Expression
PropertyOrField(
Constant(<<closure_object>>),
"MyCustomObject"
)
We can't write something like this in code, because our code doesn't have access to the <<closure_object>> instance.
Related
I was looking around here for the answer to this question, and I found a lot of similar questions
Passing just a type as a parameter in C#
X is a variable but used like a type when trying to cast
how to adjust "is a type but is used like a variable"?
How to pass an Object type to Type parameter in C#
Generic List<T> as parameter on method, Initializing a Generic variable from a C# Type Variable
How do I use reflection to call a generic method?
Reflection To Execute Class With Generic Type
but I wasn't able to use any of them to solve my particular issue.
Basically, I have a class (that I don't want to modify) that is activated in a form like so:
var myEvent = new EventListener<KeyboardEvent/*or other type of event*/>((e) => {
///do stuff with event "e"
});
I want to make a function that makes a new event listener "dynamically", meaning based on a particular variable for the "event type" (forget about the function body for now, just assume they all have the same function body), like:
void makeEvent(Type eventType) {
var myEvent = new EventListener<eventType>((e) => {
///do stuff with event "e"
});
}
as many of you will know, as did those people who posted the above questions, that simple doing that will give a "variable used like a type" error, and it won't work, and many of them suggested using "reflection" to get around this, like (from Reflection To Execute Class With Generic Type):
ar instance = Activator.CreateInstance(implementation);
var results = this.GetType()
.GetMethod("CheckForMessages", BindingFlags.NonPublic | BindingFlags.Instance)
.MakeGenericMethod(interfaceUsesType)
.Invoke(this, null) as object[];
if(results.Count() > 0)
instance.GetType()
.GetMethod("DoThis")
.Invoke(instance, new object[] {results});
or (from Initializing a Generic variable from a C# Type Variable):
Animal a = MyFavoriteAnimal();
var contextType = typeof(EsbRepository<>).MakeGenericType(a.GetType());
dynamic context = Activator.CreateInstance(contextType);
context.DoAnimalStuff();
So these answers theoretically make a class definition, but in my case I need to do 2 things, #1: make the actual class of the EventListener, and #2 actually give the class a body (via the lambda expression above), so how can I do that with Activator.CreateInstance ? Or Is there any other way?
Basically I can't use a lambda in the object[], because its not an object, and if I use an Action of some kind that is an object, then I would need to pass in a generic type, and I'm back to where I started, for example I could theoretically do:
var myType = typeof(EventListener<>).MakeGenericType(eventType);
Activator.CreateInstance(myType, new object[] {
new Action<KeyboardEvent>(e => {})
});
which would compile, but then I'm back to where I started in the first place, because "KeyboardEvent" is itself what I need to change, and if I do:
Action<myDynamicTypeVariable>(e=>{})
I get the same "variable is used as type" error...
Isn't there just some kind of way to actually use a variable as a type?
Or is there a way to set the body of a function after the class instance has been formed?
Or how can I pass in a generic function as one of the object[] arguments without having to specify the type of the function and without using lambdas?
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();
In C# we can instantiate a Delegate through a method reference to static method or an instance method. Example:
Func<object, object, bool> refEquals = Object.ReferenceEquals; // target = null
Func<string> toStr = new Object().ToString; // target = new Object()
For the latter the Delegate’s target is the new Object(), whereas the former has a null target.
But, how can I instantiate a Delegate for the ToString method reference without a pre-defined target? In this case, I would like that the ToString’s target would be bound to the Delegate’s argument. This could be useful, for instance, to call a certain instance method to all items of an IEnumerable<T>:
Func<object, string> toStr = Object.ToString; // the target (this) would be the Func’s argument
IEnumerable<T> dataSrc = ...
IEnumerable<String> dataSrc = dataSrc.Select(toStr);
However, first line does not compile:
error CS0123: No overload for 'ToString' matches delegate 'System.Func'
Java 8 provides this feature through Reference to an Instance Method of an Arbitrary Object. How can I achieve this same feature in .Net?
I know that we could surpass this limitation with a lambda expression, such as:
Func<Object, String> toStr = item => item.ToString();
However, this incurs in a further indirection to call the ToString instance method and for that reason I am not considering this workaround as a valid solution for my question.
Via Reflection, you can get an equivalent behavior to that one described in Java 8. You can create an instance of a Delegate with a null target and dynamically binding its first argument to the this method parameter. For your example you can create the toStr delegate in the following way:
MethodInfo methodToStr = typeof(object).GetMethod("ToString");
Func<Object, String> toStr = (Func<Object, String>) Delegate.CreateDelegate(
typeof(Func<Object, String>),
methodToStr);
I have this method:
public void DoSomething<T>(Expression<Func<T, object>> method)
{
}
If this method is called like this:
DoSomething(c => c.SomeMethod(new TestObject()));
... how do I get the value of the parameter that was passed into SomeMethod()?
If the parameter is a value type, this works:
var methodCall = (MethodCallExpression)method.Body;
var parameterValue = ((ConstantExpression)methodCall.Arguments[0]).Value;
However, when I pass in a reference type, methodCall.Arguments[0] is a MemberExpression, and I can't seem to figure out how to write code to get the value out of it.
Here is the answer (inspired by Akash's answer):
LambdaExpression lambda = Expression.Lambda(methodCall.Arguments[0]);
var compiledExpression = lambda.Compile();
return compiledExpression.DynamicInvoke();
You will have to evaluate member expression manually, MemberExpression contains "Expression" which is the container object of Member specified, to do this you can crete Lamda of your arguement and compile and execute it.
LamdaExpression l = Expression.Lambda(methodCall.Arguments[0]);
var c = l.Compile();
var v = c.Invoke();
So whatever you pass, you will get it in "v" variable.
This isn't really a matter of value type or reference type - it's a matter of a constant expression or not-constant expression. I'm sure your existing code would fail if you called
DoSomething(c => c.SomeMethod(DateTime.Now));
as well.
Basically, the argument to the method is just an expression. It's not a value. You could potentially compile that expression and then execute it to get the value at that point in time, but it's important to understand that an expression isn't a value in itself. In the case of a constant expression it's easy, but taking the DateTime.Now example, by definition the evaluated value of the expression changes over time :)
What are you trying to do with the argument? What's the bigger picture here?
Firstly, what Jon said.
There are no values to get ahold of, it's all just expressions. What might be of interest is the NewExpression, which has a Constructor property; this property contains the reflected constructor that would be called if you compiled expression and ran the resulting delegate. You could manually invoke that constructor and get an instance of what the user was intending on instantiating.
I'm trying to get the name of a method on a type using a lambda expression. I'm using Windows Identity Foundation and need to define access policies with the type name with namespace as a resource and the method name as the action. Here is an example.
This is the type I would be getting the type name and method name from:
namespace My.OrderEntry {
public class Order {
public void AddItem(string itemNumber, int quantity) {}
}
}
This is how I would like to define the access policy through a DSL:
ForResource<Order>().Performing(o => o.AddItem).AllowUsersHaving(new Claim());
From that statement, I would like to get "My.OrderEntry.Order" as the resource and "AddItem" as the action. Getting the type name with namespace is no problem, but I don't think I can use a lambda for a method like I'm trying to do.
public static IPermissionExp Performing<T>(
this IActionExp<T> exp,
Func<T, delegate???> action) {} //this is where I don't know what to define
Is this sort of thing even possible to do? Is there another way to do this sort of thing without using magic strings?
There are two ways to do this:
1: You could make overloads that take the various Func and Action delegates(eg Expression<Func<T, Func<TParam1,TParam2, TReturn>>. Note that your callers would need to specify the generic parameters explicitly, either in the method call or by creating the delegate. This would be used like this:
ForResource<Order>().Performing(o => new Action<string>(o.AddItem)).AllowUsersHaving(new Claim());
2: You could take an Expression<Action> that contains a method call, and parse out the MethodInfo being called from the expression tree. This would be used like this:
ForResource<Order>().Performing(o => { o.AddItem(null); }).AllowUsersHaving(new Claim());
It looks like this is what you are looking for if you want the name of the action delegate method passed in to the Performing function.
public static IPermissionExp Performing<T>(
this IActionExp<T> exp,
Expression<Action<T, string, int>> action)
{
var expression = action.Body as MethodCallExpression;
string actionMethodName = string.Empty;
if (expression != null)
{
actionMethodName = expression.Method.Name;
}
// use actionMethodName ("AddItem" in the case below) here
}
This would allow you to call the method like this...
ForResource<Order>().Performing((o, a, b) => o.AddItem(a, b)).AllowUsersHaving(new Claim());
I recently did a thing at work where you defined the a method using a lambda, which the internal object then took the name of. You could use strings as well, or pass in a MethodInfo but the first one isn't really type safe (and typos are a big risk), and the latter is not very elegant.
Basically I had a method like this (this is not the exact method, it is a bit more advanced):
public void SetRequest(Request req, Expression<Func<Service, Func<long, IEnumerable<Stuff>>> methodSelector);
The key here is the "Expression" thing, this lets you "select" a method like this:
SetRequest(req, service => service.SomeMethodTakingLongReturningStuffs);
Method selector is made into a expression tree which you can then fetch different bits of data from. I don't recall exactly what the resulting tree looks like, it also depends on how your lambdas look.
You could pass it in as a Action instead, which doesn't force any return type. It is still a little messy though, because you have to pass some arguments to the method in order for it to compile.