is it possible to call a delegate stored in a variable by its variable name (as a string)? i guess i'd have to use reflection mechanism, but i'm not getting anywhere
example code:
class Demo {
public delegate int DemoDelegate();
private static int One() {
return 1;
}
private static void CallDelegate(string name) {
// somehow get the value of the variable with the name
// stored in "name" and call the delegate using reflection
}
private static void CallDelegate(string name, DemoDelegate d) {
d();
}
static void main(string[] args) {
DemoDelegate one = Demo.One;
CallDelegate(one);
// this works, but i want to avoid writing the name of the variable/delegate twice:
CallDelegate("one", one);
}
}
is this even possible? if so how? if not, then i have to use the second form, bad luck
Variables barely exist. The only way to reliably call-by-string (in this scenario) would be to store the delegates in a dictionary:
Dictionary<string, DemoDelegate> calls = new Dictionary<string, DemoDelegate>
{
{"one",one}, {"two",two}
}
Now store that dictionary somewhere (in a field, typically), and do something like:
private int CallDelegate(string name) {
return calls[name].Invoke(); // <==== args there if needed
}
Yes, it is possible, as long as you use Linq Expressions, and little reflection.
Take a look at this code, it does something simillar to what I think you want:
using System;
using System.Linq.Expressions;
using System.Reflection;
using System.Collections.Generic;
namespace q6010555
{
class Demo
{
static List<string> varNamesUsed = new List<string>();
public delegate int DemoDelegate();
private static int One()
{
return 1;
}
private static void CallDelegate(Expression<Func<DemoDelegate>> expr)
{
var lambda = expr as LambdaExpression;
var body = lambda.Body;
var field = body as MemberExpression;
var name = field.Member.Name;
var constant = field.Expression as ConstantExpression;
var value = (DemoDelegate)((field.Member as FieldInfo).GetValue(constant.Value));
// now you have the variable name... you may use it somehow!
// You could log the variable name.
varNamesUsed.Add(name);
value();
}
static void Main(string[] args)
{
DemoDelegate one = Demo.One;
CallDelegate(() => one);
// show used variable names
foreach (var item in varNamesUsed)
Console.WriteLine(item);
Console.ReadKey();
}
}
}
public void Fire(string name)
{
FieldInfo field = this.GetType().GetField(name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
if (field != null)
{
Delegate method = field.GetValue(this) as Delegate;
if (method != null)
{
method.Method.Invoke(method.Target, new object[0]);
}
}
}
Obviously restricts you from having parameterized delegates.
You can't really access variables in another stack frame (although I think it is possible using hackery around the StackFrame class). Instead, you'll be wanting to pass an Delegate object around and use methods like DynamicInvoke, if you want to invoke a generalised delegate in a reflection-like manner.
Related
By examining an expression tree i can get the value of a constant, instance field and property but not a local variable defined in a method.
Executing the following will output 1, 2, 3 (from the constant, instance field and property) then an exception as i don't know how to get the instance on which the FieldInfo is declared in order to call GetValue() for the local variable.
using System;
using System.Linq.Expressions;
using System.Reflection;
namespace Example
{
class Program
{
private int _intField = 2;
static void Main()
{
new Program().Run();
Console.ReadLine();
}
private void Run()
{
IntProp = 3;
var intVariable = 4;
Test(() => 1);
Test(() => _intField);
Test(() => IntProp);
Test(() => intVariable);
}
public int IntProp { get; set; }
void Test<T>(Expression<Func<T>> func)
{
var body = func.Body;
if (body.NodeType == ExpressionType.Constant)
{
Console.WriteLine(((ConstantExpression)body).Value);
}
else
{
var memberExpression = body as MemberExpression;
var #object = memberExpression.Member.DeclaringType == GetType()
? this
: null; //Can I do anything here? Instance of the method the variable is defined in?
if (memberExpression.Member.MemberType == MemberTypes.Field)
{
Console.WriteLine(((FieldInfo)memberExpression.Member).GetValue(#object));
}
else if (memberExpression.Member.MemberType == MemberTypes.Property)
{
Console.WriteLine(((PropertyInfo)memberExpression.Member).GetValue(#object));
}
}
}
}
}
The local variable which has been captured by the lambda and included in the expression tree, will at that time really be a field on some compiler-generated class. This works on my version of .NET:
void Test<T>(Expression<Func<T>> func)
{
var body = func.Body;
if (body.NodeType == ExpressionType.Constant)
{
Console.WriteLine(((ConstantExpression)body).Value);
}
else
{
var memberExpression = (MemberExpression)body;
var #object =
((ConstantExpression)(memberExpression.Expression)).Value; //HERE!
if (memberExpression.Member.MemberType == MemberTypes.Field)
{
Console.WriteLine(((FieldInfo)memberExpression.Member).GetValue(#object));
}
else if (memberExpression.Member.MemberType == MemberTypes.Property)
{
Console.WriteLine(((PropertyInfo)memberExpression.Member).GetValue(#object));
}
}
}
Of course, you can also "cheat":
void Test<T>(Expression<Func<T>> func)
{
Console.WriteLine(func.Compile()());
}
No, you cannot.
Reflection does not extend to reading the values of method variable.
It only handles the declaration metadata of variables. And even then, the compiler may have removed the variable you thought you declared. You allready can access to properties, fields.
No, you cannot because those variables are simply not available outside the method their scope.
No you can't with reflection. But there are other methods to do so. As an example, I show you how to export a variable out of the functions' lexical scope.
Say you have a method like this:
private void f(int x)
{
// your code here
}
You also have a piece of code like this:
int x_in_f;
f(3);
x_in_f = /* I want to have the value here */;
To get the value out of f() you must export a getter function. As f() returns void, you just could return the getter. In a general case (when f() has a non-void return type) you can leverage an out parameter. Here are both variants:
private Func<int> f(int x)
{
// your code here
return () => { return x; };
}
or through the out parameter:
private void f(int x, out Func<int> g)
{
// your code here
g = () => { return x; };
}
The code would then be:
int x_in_f;
Func<int> g;
g = f(3);
x_in_f = g(); // this will return the value of x as it was passed to f()
or through the out parameter invoke f() as follows:
f(3, out g);
At that point you can pass g() around to other functions:
private void h(Func<int> getx)
{
// your code here
int x = getx();
// now you have the value of x inside the h() function
}
and the invocation with h():
Func<int> g = f(3);
// ...
h(g);
I hope this helps or at least shows how to use closures to circumvent lexical scoping.
For the designers out there, this is the Object Capability Model. This is a video by Douglas Crockford on how to use it for security purposes in Javascript. It translates to C# and other purposes easily, as I've shown above.
public void SomeMethod(string sampleString)
{ var helloworld = sampleString; }
Is it possible to determine if a particular symbol is a local variable, class field or method's parameter? e.g. if I call a FindSymbolAtPosition on the sampleString, will i be able to tell that the sampleString symbol is a method's parameter or variable?
EDIT: the requirement is that it must work from coding-time, for my static code analysis tool that im building with roslyn
You can't get it directly via properties, because in var helloworld = sampleString;, the statement has no context that if sampleString is a parameter or not. But you can get it from the method's context like this:
static bool IsParameter(IdentifierNameSyntax name)
{
SyntaxNode node = name;
while (node != null && !(node is MethodDeclarationSyntax))
{
node = node.Parent;
}
var method = node as MethodDeclarationSyntax;
if (method != null)
{
return method
.ParameterList
.Parameters
.Any(p => p.Identifier.Text.Equals(name.Identifier.Text));
}
return false;
}
Using .Parent to get the method context of the variable, and check if any parameter in .ParameterList matches the identifier.
UPDATE Code to prove it's working:
SyntaxTree tree = CSharpSyntaxTree.ParseText(
#"using System;
using System.Collections;
using System.Linq;
using System.Text;
namespace HelloWorld
{
class Program
{
static void Main(string i)
{
var j = ""1"";
var k = i + j;
}
}
}");
var root = (CompilationUnitSyntax)tree.GetRoot();
var ns = root.Members[0] as NamespaceDeclarationSyntax;
var cls = ns.Members[0] as ClassDeclarationSyntax;
var method = cls.Members[0] as MethodDeclarationSyntax;
var statement = method.Body.Statements[1] as LocalDeclarationStatementSyntax;
var variable = statement.Declaration.Variables[0];
var binary = variable.Initializer.Value as BinaryExpressionSyntax;
var vari = binary.Left as IdentifierNameSyntax;
var varj = binary.Right as IdentifierNameSyntax;
Console.WriteLine(IsParameter(vari)); //True
Console.WriteLine(IsParameter(varj)); //False
EDIT Base on #JeroenVannevel's comment, we can use SemanticModel.GetSymbolInfo.
var compilation = CSharpCompilation.Create("test", new[] { tree });
var semanticModel = compilation.GetSemanticModel(tree, true);
var symboli = semanticModel.GetSymbolInfo(vari);
var symbolj = semanticModel.GetSymbolInfo(varj);
//check symboli.Symbol.OriginalDefinition.Kind == SymbolKind.Parameter
Its wrong to compare identifiers by syntax or by text, imagine if the IdentifierNameSyntax is the name of MemberAccessExpressionSyntax and has the same identifier as a parameter, then you would incorrectly conclude that it is a parameter even though it is a member. You should work with the SemanticModel to determine what a SymbolKind is. You can use SemanticModel.GetDeclaredSymbol on declarations and SemanticModel.GetSymbolInfo().Symbol on symbol usages. Once you have the ISymbol it's easy to determine its kind. Bear in mind that different symbols have their own "sub-kinds", for instance ITypeSymbol has TypeKind property that determines if the type is Class, Struct, Interface, Array etc., so you should check them up.
You can use the following code to get the field information for class and parameters. Note, however, the detection of the method field is unavailable. This code uses reflection to query the assembly information and enumerates and compares the results.
static class Program
{
static void Main(string[] args)
{
SomeMethod("Hello, World!!!");
Type testType = typeof(Program);
FieldInfo[] fieldInfo = testType.GetFields();
MethodInfo methodInfo = testType.GetMethod("SomeMethod");
Console.WriteLine("Parameter type:{0}", TypeOfField(fieldInfo, methodInfo, "sampleString"));
Console.WriteLine("Parameter type:{0}", TypeOfField(fieldInfo, methodInfo, "classField"));
Console.WriteLine("Parameter type:{0}", TypeOfField(fieldInfo, methodInfo, "helloWorld"));
Console.WriteLine("Parameter type:{0}", TypeOfField(fieldInfo, methodInfo, "nonexistentVariable"));
}
public static string classField = "Hello, World!!!";
public static void SomeMethod(string sampleString)
{
string helloWorld = sampleString;
}
public static string TypeOfField(FieldInfo[] fieldInfo, MethodInfo methodInfo, string fieldName)
{
if (IsClassField(fieldInfo, fieldName))
{
return "Class Field";
}
else if (IsParameter(methodInfo, fieldName))
{
return "Parameter";
}
else
{
return "Cannot determine";
}
}
private static bool IsClassField(FieldInfo[] fieldInfo, string classFieldName)
{
bool isClassField = false;
foreach (var item in fieldInfo)
{
if (item.Name == classFieldName)
{
isClassField = true;
break;
}
}
return isClassField;
}
private static bool IsParameter(MethodInfo methodInfo, string parameterName)
{
bool isParameter = false;
ParameterInfo[] paramInfo = methodInfo.GetParameters();
foreach (var item in paramInfo)
{
if (item.Name == parameterName)
{
isParameter = true;
break;
}
}
return isParameter;
}
}
You can distinguish whether you are dealing with a class field vs a method's parameter or a local variable with the keyword this. If you had a class field string called sampleString and you wanted to refer to the class field rather then the local variable/ method parameter then you would refer to it with this.sampleString. You would refer to the local variable/ method parameter as sampleString without the keyword (this). In terms of local variables and method parameters, you are not able to have a local variable and method parameter with the same name within the same method. With your code above you are referring to the sampleString parameter.
I have a class library in which I have defined a few functions f1, f2 that I would like to put them in a dictionary to later call by name. However, the reflection Type.GetMethod does not seem to be defined in the class library portable even I am using System.Reflection. Can you suggest a work around?
This is my simple piece of code for illustration
public class Class1
{
public delegate int myFunction(object o);
private Dictionary<string, myFunction> list = new Dictionary<string, myFunction>();
public Class1()
{
string[] n = { "f1", "f2" };
MethodInfo mInfo;
foreach (var i in n)
{
mInfo = typeof(Class1).GetMethod(i);
}
list.Add("f1", f1);
list.Add("f2", f2);
}
public int f1(object o)
{
System.Diagnostics.Debug.WriteLine("f1: parameter is {0} " ,o);
return 0;
}
public int f2(object o)
{
System.Diagnostics.Debug.WriteLine("f2: parameter is {0} ", o);
return 0;
}
}
my original intention was putting all my functions in my dictionary list. I can manually add:
list.Add("f1", f1);
list.Add("f2", f2);
But when I declare an array of string with the name of the function, use GetMethod to pick up the function, compiler was generating an error "Type does not contain definition for GetMethod...
Please advise.
Thanks!
Update: Compiling Error
Update with Singleton:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
namespace ClassLibrary1
{
public sealed class Class1
{
public delegate int myFunction(object o);
public Dictionary<string, myFunction> list = new Dictionary<string, myFunction>();
private static readonly Class1 _instance = new Class1();
static Class1()
{
}
public Class1()
{
string[] n = { "f1", "f2" };
MethodInfo mInfo;
foreach (var i in n)
{
mInfo = typeof(Class1).GetTypeInfo().GetDeclaredMethod(i);
//NewExpression constrExpr = Expression.New(typeof(Class1).GetTypeInfo().DeclaredConstructors.Single(ci => ci.GetParameters().Length == 0));
ParameterExpression objExpr = Expression.Parameter(typeof(object));
Expression<myFunction> expr = Expression.Lambda<myFunction>(Expression.Call(null, mInfo, objExpr), objExpr);
//Expression<myFunction> expr = Expression.Lambda<myFunction>(Expression.Call(constrExpr, mInfo, objExpr), objExpr);
list.Add(i, expr.Compile());
}
list.Add("f11", f1);
list.Add("f21", f2);
}
public static Class1 Instance
{
get
{
return _instance;
}
}
public int f1(object o)
{
System.Diagnostics.Debug.WriteLine("f1: parameter is {0} ", o);
return 0;
}
public int f2(object o)
{
System.Diagnostics.Debug.WriteLine("f2: parameter is {0} ", o);
return 0;
}
}
}
First of all, most PCL profiles are using TypeInfo for type information, see e.g. here and here. TypeInfo also comes with a slightly different set of methods.
So, instead of writing
typeof(Class1).GetMethod(i)
you should thus write:
typeof(Class1).GetTypeInfo().GetDeclaredMethod(i)
But even if you use the above expression to obtain MethodInfo, you cannot (to my knowledge) immediately convert this object into a myFunction delegate.
One way of solving this problem would be to use expression trees. You would then need to formulate an Expression<myFunction> object which you would compile into a myFunction delegate.
I think you can do something like this:
Expression<myFunction> expr =
Expression.Lambda<myFunction>(
Expression.Call(
constrExpr,
typeof(Class1).GetTypeInfo().GetDeclaredMethod(i),
objExpr),
objExpr);
list.Add(i, expr.Compile());
where constrExpr is an expression for creating an instance of Class1 using the default constructor
NewExpression constrExpr =
Expression.New(
typeof(Class1).GetTypeInfo().DeclaredConstructors
.Single(ci => ci.GetParameters().Length == 0));
and objExpr is a representation of the object o parameter
ParameterExpression objExpr = Expression.Parameter(typeof(object));
With these changes, you should be able to invoke an arbitrary method in your dictionary, like this:
int i = list["f1"]("hello");
int j = list["f2"](20.0);
Given the following set of classes:
public class MyClass
{
public int MyInt { get; set; }
}
public class ObjectProcessor
{
public int ProcessObject(MyClass myClass)
{
return myClass.MyInt ++;
}
}
public class Runner
{
public void Run()
{
var classToPass = new MyClass();
FuncExecutor.ExecuteAction<MyClass>(x => x.ProcessObject(classToPass));
}
}
public static class FuncExecutor
{
public static void ExecuteAction<T>(Expression<Func<ObjectProcessor, int>> expression)
{
// var func = expression.Compile(); ... does having an Expression help?
// How can I get a reference to 'classToPass' at this point?
// The 'classToPass' Type is known to be 'T', in this case 'MyClass'.
}
}
From within the ExecuteAction method, how can I get a reference to the classToPass instance that was passed in to ProcessObject?
EDIT: The comments have highlighted the complexity of trying to parse Expression Trees which could vary widely in their composition.
However, in this particular case there are two facts which cut down this variation considerably:
ProcessObject will only ever take a single parameter.
The parameter type is known in advance.
Code altered to express this.
To answer very specifically:
public class Runner
{
public void Run()
{
var classToPass = new MyClass();
classToPass.MyInt = 42;
FuncExecutor.ExecuteAction(x => x.ProcessObject(classToPass));
}
}
public class FuncExecutor
{
public static void ExecuteAction(Expression<Func<ObjectProcessor, int>> expression)
{
var lambdaExpression = (LambdaExpression)expression;
var methodCallExpression = (MethodCallExpression)lambdaExpression.Body;
var memberExpression = (MemberExpression)methodCallExpression.Arguments[0];
var constantExpression = (ConstantExpression)memberExpression.Expression;
var fieldInfo = (FieldInfo)memberExpression.Member;
var myClassReference = (MyClass) fieldInfo.GetValue(constantExpression.Value);
Console.WriteLine(myClassReference.MyInt); // prints "42"
}
}
Please note that when you pass the lambda to the ExecuteAction method, you capture a local variable reference (classToPass). The compiler will generate some code to handle that properly. More precisely, it will generate a type with a single member (a field) of type MyClass to hold the reference and use it from this point. That's why you'll get a MemberExpression in the argument expression list.
Since you can't directly manipulate this generated type, you can't just use the member expression Value property. But you can dynamically invoke the member accessor using the MemberInfo and the target reference (an instance of the compiler generated type).
I would not rely on this code.
You can read more about lambda related compiler generated code here, for example: http://thewalkingdev.blogspot.fr/2012/04/c-lambda-expressions-and-closures.html
The easiest way is to pass the instance as parameter and let ExecuteAction take care of calling the process method using that instance. To do this it is necessary to give your code a little bit of structure using a generic object processor interface:
public interface IObjectProcessor<T> {
public int ProcessObject(T instance);
}
public class MyClassProcessor : IObjectProcessor<MyClass> {
public int ProcessObject(MyClass myClass) {
return myClass.MyInt ++;
}
}
public class Runner {
public void Run() {
var classToPass = new MyClass();
var processor = new MyClassProcessor();
FuncExecutor.ExecuteAction<MyClass>(processor, classToPass);
}
}
public class FuncExecutor {
public static void ExecuteAction<T>(IObjectProcessor<T> processor, T obj) {
int result = processor.ProcessObject(obj);
}
}
This design could be a little annoying especially if your processor are "stateless" and if you really need a Func as parameter. In this case you can drop the interface and use static processors:
public class MyClassProcessor
public static int ProcessObject(MyClass myClass) {
return myClass.MyInt ++;
}
}
public class Runner {
public void Run() {
var classToPass = new MyClass();
FuncExecutor.ExecuteAction<MyClass>(MyClassProcessor.ProcessObject, classToPass);
}
}
public class FuncExecutor {
public static void ExecuteAction<T>(Func<T, int> process, T obj) {
int result = process(obj);
}
}
I suppose in some ways either (or both) Delegate or MethodInfo qualify for this title. However, neither provide the syntactic niceness that I'm looking for. So, in short, Is there some way that I can write the following:
FunctionPointer foo = // whatever, create the function pointer using mechanisms
foo();
I can't use a solid delegate (ie, using the delegate keyword to declare a delegate type) because there is no way of knowing till runtime the exact parameter list. For reference, here's what I've been toying with in LINQPad currently, where B will be (mostly) user generated code, and so will Main, and hence for nicety to my users, I'm trying to remove the .Call:
void Main()
{
A foo = new B();
foo["SomeFuntion"].Call();
}
// Define other methods and classes here
interface IFunction {
void Call();
void Call(params object[] parameters);
}
class A {
private class Function : IFunction {
private MethodInfo _mi;
private A _this;
public Function(A #this, MethodInfo mi) {
_mi = mi;
_this = #this;
}
public void Call() { Call(null); }
public void Call(params object[] parameters) {
_mi.Invoke(_this, parameters);
}
}
Dictionary<string, MethodInfo> functions = new Dictionary<string, MethodInfo>();
public A() {
List<MethodInfo> ml = new List<MethodInfo>(this.GetType().GetMethods());
foreach (MethodInfo mi in typeof(Object).GetMethods())
{
for (int i = 0; i < ml.Count; i++)
{
if (ml[i].Name == mi.Name)
ml.RemoveAt(i);
}
}
foreach (MethodInfo mi in ml)
{
functions[mi.Name] = mi;
}
}
public IFunction this[string function] {
get {
if (!functions.ContainsKey(function))
throw new ArgumentException();
return new Function(this, functions[function]);
}
}
}
sealed class B : A {
public void SomeFuntion() {
Console.WriteLine("SomeFunction called.");
}
}
You say you want to keep the number and type of parameters open, but you can do that with a delgate:
public delegate object DynamicFunc(params object[] parameters);
This is exactly the same thing you currently have. Try this:
class Program
{
static void Main(string[] args)
{
DynamicFunc f = par =>
{
foreach (var p in par)
Console.WriteLine(p);
return null;
};
f(1, 4, "Hi");
}
}
You can think of an instance-method delegate as very similar to your Function class: an object an a MethodInfo. So there's no need to rewrite it.
Also function pointers in C and C++ are not any closer to what you need: they cannot be bound to an object instance and function, and also they are statically typed, not dynamically typed.
If you want to "wrap" any other method in a DynamicFunc delegate, try this:
public static DynamicFunc MakeDynamicFunc(object target, MethodInfo method)
{
return par => method.Invoke(target, par);
}
public static void Foo(string s, int n)
{
Console.WriteLine(s);
Console.WriteLine(n);
}
and then:
DynamicFunc f2 = MakeDynamicFunc(null, typeof(Program).GetMethod("Foo"));
f2("test", 100);
Note that I'm using a static method Foo so I pass null for the instance, but if it was an instance method, I'd be passing the object to bind to. Program happens to be the class my static methods are defined in.
Of course, if you pass the wrong argument types then you get errors at runtime. I'd probably look for a way to design your program so that as much type information is captured at compile time as possible.
Here's another bit of code you could use; Reflection is rather slow, so if you expect your Dynamic function calls to be called frequently, you don't want method.Invoke inside the delegate:
public delegate void DynamicAction(params object[] parameters);
static class DynamicActionBuilder
{
public static void PerformAction0(Action a, object[] pars) { a(); }
public static void PerformAction1<T1>(Action<T1> a, object[] p) {
a((T1)p[0]);
}
public static void PerformAction2<T1, T2>(Action<T1, T2> a, object[] p) {
a((T1)p[0], (T2)p[1]);
}
//etc...
public static DynamicAction MakeAction(object target, MethodInfo mi) {
Type[] typeArgs =
mi.GetParameters().Select(pi => pi.ParameterType).ToArray();
string perfActName = "PerformAction" + typeArgs.Length;
MethodInfo performAction =
typeof(DynamicActionBuilder).GetMethod(perfActName);
if (typeArgs.Length != 0)
performAction = performAction.MakeGenericMethod(typeArgs);
Type actionType = performAction.GetParameters()[0].ParameterType;
Delegate action = Delegate.CreateDelegate(actionType, target, mi);
return (DynamicAction)Delegate.CreateDelegate(
typeof(DynamicAction), action, performAction);
}
}
And you could use it like this:
static class TestDab
{
public static void PrintTwo(int a, int b) {
Console.WriteLine("{0} {1}", a, b);
Trace.WriteLine(string.Format("{0} {1}", a, b));//for immediate window.
}
public static void PrintHelloWorld() {
Console.WriteLine("Hello World!");
Trace.WriteLine("Hello World!");//for immediate window.
}
public static void TestIt() {
var dynFunc = DynamicActionBuilder.MakeAction(null,
typeof(TestDab).GetMethod("PrintTwo"));
dynFunc(3, 4);
var dynFunc2 = DynamicActionBuilder.MakeAction(null,
typeof(TestDab).GetMethod("PrintHelloWorld"));
dynFunc2("extraneous","params","allowed"); //you may want to check this.
}
}
This will be quite a bit faster; each dynamic call will involve 1 typecheck per param, 2 delegate calls, and one array construction due to the params-style passing.