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);
Related
I have Expression<Action<T>> where Action is call of function, but function result is not used. Let's consider the following code sample:
using System;
using System.Linq.Expressions;
namespace ConsoleApp
{
class Program
{
public class MyArg
{
public int Data { get; set; }
}
public class MyExecutor
{
public bool Executed { get; set; }
public int MyMethod(int simpleArg, MyArg complexArg)
{
int result = simpleArg + complexArg.Data;
this.Executed = true;
return result;
}
}
static void Main(string[] args)
{
Expression<Action<MyExecutor>> expr = t => t.MyMethod(2, new MyArg { Data = 3 });
var executor = new MyExecutor();
Action<MyExecutor> action = expr.Compile();
action(executor);
Console.WriteLine(executor.Executed); // true
}
}
}
There can lot of different actions, with different number of arguments. In all cases I have only such kind of expr which always calls a function and that function always returns the same type, in my example above it is int.
I need to have something like this:
static Expression<Func<MyExecutor, int>> ToExpressionOfFunc(Expression<Action<MyExecutor>> expr)
{
// TODO
throw new NotImplementedException();
}
to be able to make a call like this:
Expression<Func<MyExecutor, int>> funcExpr = ToExpressionOfFunc(expr);
Func<MyExecutor, int> func = funcExpr.Compile();
int result = func(executor);
Console.WriteLine(result); // should print 5
I have a feeling that this should be possible but have no ideas where to start from. I see in debug that there is an expr.Body.Method with desired ReturnType of Int32, but not clear how to extract it properly to the new Expression<Func>.
It's simple, just create a new Expression<Func<MyExecutor, int>> using the body and parameters from the existing expression:
static Expression<Func<MyExecutor, int>> ToExpressionOfFunc(Expression<Action<MyExecutor>> expr)
{
return Expression.Lambda<Func<MyExecutor, int>>(expr.Body, expr.Parameters);
}
Note that this throws an exception if expr is not of return type int.
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 would like to do some similar process within a loop like this by calling a generic method with different types.
AAA, BBB are all classes. CreateProcessor is a generic method in the class of MyProcessor.
new List<Type> {typeof (AAA), typeof (BBB)}.ForEach(x =>
{
var processor = MyProcessor.CreateProcessor<x>(x.Name);
processor.process();
});
This doesn't compile, I got the error saying Cannnot resolve symbol x.
Technically, how to achieve it? (I know the strategy pattern is better...)
Reflection is required to deal with the Type class:
new List<Type> { typeof(AAA), typeof(BBB) }.ForEach(x => {
var type = typeof(MyClass<>).MakeGenericType(x);
dynamic processor = Activator.CreateInstance(type, x.Name);
processor.process();
});
Sorry, I updated my question. I intended to call a generic method actually.
var method = typeof(MyProcessor).GetMethod("CreateProcessor", new Type[] { typeof(string) });
new List<Type> { typeof(AAA), typeof(BBB) }.ForEach(x =>
{
dynamic processor = method.MakeGenericMethod(x).Invoke(null, new[] { x.Name });
processor.process();
});
You have to use reflection to create a generic object like that. This page from Microsoft has an excellent rundown on what you need to do: How to: Examine and Instantiate Generic Types with Reflection
This is how you would create a new variable using only type information, by using dynamic you are able to call any method which you know exists for all of the types. I would suggest (assuming these types are your own classes) you implement an interface baseclass or something for these if possible, it simplify your quite a lot...
new List<Type> { typeof(string), typeof(int) }.ForEach(x =>
{
dynamic processor = Activator.CreateInstance(x);
processor.ToString();
processor.CallAnyMethodHere();
processor.Process();
});
Edited code - Adding a clear example
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
public class mainClass
{
public static void Main(string[] args)
{
new List<Type> { typeof(StringBuilder), typeof(Int64) }.ForEach(x =>
{
dynamic instance = Activator.CreateInstance(x);
DoSomething(instance);
});
Console.ReadKey();
}
public static void DoSomething(StringBuilder stringBuilder)
{
Console.WriteLine("StringBuilder overload");
}
public static void DoSomething(Int64 int64)
{
Console.WriteLine("Int64 overload");
}
}
Edit 2 - Only call generic method
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using System.Linq;
public class mainClass
{
public static void Main(string[] args)
{
new List<Type> { typeof(StringBuilder), typeof(Int64) }.ForEach(x =>
{
var methodInfoArray = typeof(mainClass).GetMethods();
var methodInfo = methodInfoArray.First(mi => mi.Name == "DoSomething" && mi.IsGenericMethodDefinition);
var genericMethod = methodInfo.MakeGenericMethod(new Type[] { x });
var blah = genericMethod.Invoke(null, new object[] { "Hello" }) as MethodInfo;
});
Console.ReadKey();
}
public static void DoSomething<T>(string variable)
{
Console.WriteLine("DoSomething<T> " + typeof(T) + " overload - " + variable);
}
public static void DoSomething(string variable)
{
Console.WriteLine("DoSomething - " + variable);
}
}
I have been playing around with LINQ to Z3 for fun (not production use).
I've ended up with this syntax as a start:
var i = 123;
var test2 = from t in TheormProver.NewTheorm()
let f = TheormProver.Func<int, bool>()
let a = TheormProver.Int
let g = TheormProver.Func<bool, int>()
where !f(a * 2) && g(f(g(f(4)))) == i * a && a < g(f(a))
select new { f = f.ToString(), g = g.ToString(), a, asd = "Test extra property" };
var solution = test2.Solve(); // Edited in for clarification
// note that test2 is a TheormProver<T> which has a "T Solve()" method defined.
The static TheromProver.Int and TheormProver.Func methods/properties simply return a basic type (as per their name) currently.
Moving forwards I want to make a sort of Variable<T> type that contains more information than just a value.
TL;DR: The problem I'm having is that I want f and g variables to be a custom type that I can add fields and properties to, but I still want to be able to use them with the syntax I've got in the where clause (i.e. as a method/Func).
So, How do I create a custom type that can be used in method syntax while adding/having my own properties?
Note that I don't care if calling the method does nothing, or doesn't work as I'll be manipulating the where clause so they'll never get invoked/executed.
Example:
var test2 = from t in TheormProver.NewTheorm()
let f = TheormProver.Func<int, bool>()
let a = TheormProver.Int
where !f(a * 2) && a > 3 // f is used to create a method call expression
select new { f , a };
var testSolution = test2.Solve();
var fSolution = testSolution.f; // F is its own type with unique properties/fields.
var fConstraints = fSolution.Constraints;
var fSomeProperty = fSolution.SomeProperty;
foreach(var constraint in fConstraints)
{
//.....
}
I've mocked up a quick example of the work in progress syntax I have so far:
http://liveworkspace.org/code/3Fm6JM$0
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
namespace ConsoleApplication1
{
class TheormProver
{
public static int Int { get { return default(int); } } // Really this would return my Variable<int>
public static Func<T, TResult> Func<T, TResult>() { return default(Func<T, TResult>); } // Really this would return my Variable<Func<T, TResult>>
protected List<Expression> Constraints; // Holds constraints / where clauses that get translated into the Z3 language
//This gets called when we do the first "let" and gets us into the correctly typed world with a generic parameter
public virtual TheormProver<T> Select<T>(Func<TheormProver, T> sel)
{
return new TheormProver<T>(Constraints);
}
}
// This is what the user of the library sees and is returned by a from t in new TheormProver(). T will be the anonymous type from the last let
class TheormProver<T> : TheormProver
{
public TheormProver(List<Expression> Constraints)
{
}
// This gets called on subsequent "let"s, going from the anonymous type with one property "f" to one with 2, "f, g". Chaining this way allows as many lets as we want
public virtual TheormProver<U> Select<U>(Expression<Func<T, U>> sel)
{
return new TheormProver<T, U>(sel, Constraints.ToList());
}
public virtual TheormProver<T> Where(Expression<Func<T, bool>> constraint)
{
var result = (TheormProver<T>)this; // This should be a clone to allow composable queries
result.Constraints.Add(constraint);
return result;
}
public virtual T Solve(out bool foundSolution)
{
// TODO: Call Z3 and get a solution
foundSolution = false;
return default(T);
}
}
internal class TheormProver<T, U> : TheormProver<U>
{
private LambdaExpression Selector;
private TheormProver<T> InternalTheorumProver;
public TheormProver(Expression<Func<T, U>> selector, List<Expression> constraints)
: base(constraints)
{
Selector = selector;
InternalTheorumProver = new TheormProver<T>(constraints);
}
}
class Program
{
static void Main(string[] args)
{
var test = from t in new TheormProver()
let f = TheormProver.Func<int, bool>()
let g = TheormProver.Func<bool, int>()
let a = TheormProver.Int
where g(f(a)) == 0
select new { f, g, a };
bool foundSolution;
var testSolution = test.Solve(out foundSolution);
}
}
}
I've created a simple 'testbed' for your original code: http://liveworkspace.org/code/3Bl7wC$0.
With, a bit of dynamic magic, you can have the following class as a drop-in replacement for Func<T1, T2>:
public class MyCallable<T1, T2> : DynamicObject
{
private readonly Expression<Func<T1, T2> > _wrapped;
private readonly Func<T1, T2> _compiled;
public MyCallable(Expression<Func<T1, T2>> towrap)
{
_wrapped = towrap; _compiled = _wrapped.Compile();
}
public override bool TryInvoke(InvokeBinder binder, object[] args, out object result)
{
if ( (args.Length == 1) &&
(args[0].GetType() == typeof(T1)))
{
Console.WriteLine(#"Invoking ""{0}"" on {1}", _wrapped, args[0]);
result = _compiled((T1) args[0]);
return true;
}
else
{
//throw new ArgumentException("Cannot invoke " + _wrapped + " with the arguments passed");
result = null;
return false;
}
}
}
As you can see, it defines you class as being "dynamic" and allows you to try and invoke it as if it were a delegate/function/... a general callable:
// in "TheormProver"
public static dynamic Func<T1, T2>() { return new MyCallable<T1, T2>(arg1 => default(T2)); }
Here's proof it works: http://liveworkspace.org/code/4kBypd$0
Output:
Invoking "arg1 => False" on 0
Invoking "arg1 => False" on 4
Invoking "arg1 => 0" on False
Invoking "arg1 => False" on 0
Invoking "arg1 => 0" on False
Invoking "arg1 => False" on 0
Invoking "arg1 => 0" on False
Full code for reference:
using System;
using System.Linq;
using System.Linq.Expressions;
using System.Dynamic;
public class Program
{
public class MyCallable<T1, T2> : DynamicObject
{
private readonly Expression<Func<T1, T2> > _wrapped;
private readonly Func<T1, T2> _compiled;
public MyCallable(Expression<Func<T1, T2>> towrap)
{
_wrapped = towrap; _compiled = _wrapped.Compile();
}
public override bool TryInvoke(InvokeBinder binder, object[] args, out object result)
{
if ( (args.Length == 1) &&
(args[0].GetType() == typeof(T1)))
{
Console.WriteLine(#"Invoking ""{0}"" on {1}", _wrapped, args[0]);
result = _compiled((T1) args[0]);
return true;
}
else
{
//throw new ArgumentException("Cannot invoke " + _wrapped + " with the arguments passed");
result = null;
return false;
}
}
}
public static class TheormProver
{
public static object[] NewTheorm() { return new object[] { 1 }; }
public static dynamic Func<T1, T2>() { return new MyCallable<T1, T2>(arg1 => default(T2)); }
public static int Int { get; set; }
}
public static void Main(string[] args)
{
var i = 123;
var test2 = from t in TheormProver.NewTheorm()
let f = TheormProver.Func<int, bool>()
let a = TheormProver.Int
let g = TheormProver.Func<bool, int>()
where !f(a * 2) && g(f(g(f(4)))) == i * a && a < g(f(a))
select new { f = f.ToString(), g = g.ToString(), a, asd = "Test extra property" };
test2.ToList().ForEach(Console.WriteLine);
}
}
You can't add custom members to delegate types and you cannot overload operator () in C#. That leaves you with extension methods.
Now, you don't want to add extensions to very general delegate types like Func<int, int> because that pollutes the namespace. I suggest you create custom delegates like this:
delegate TResult Z3Func<T1, TResult>(T1 arg1);
Then you can add extensions to Z3Func.
The extension calls will end up as static method calls in the expression tree you are analyzing.
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.