C# Function as parameter - c#

I need help. I'm making a programm and i have a problem.
I have a constructor with delegate already:
public delegate bool delIsDone(int curState, int needState);
public Progress(delIsDone doneFunction) { ... }
I need to pass it without creating it outside of creation:
public bool check() { return true }
Progress p = new Progress(check);
I need to do something like this:
Progress p = new ProgressChecker(bool check(int currentProgress, int needProgress) {
return currentProgress < needProgress;
});
Where ProgressChecker is a class that have method that check progress.
In loop i execute this function to get result. If function return "true" it's mean that "Achievement geted" and i need to hold it.
Thx for help

In the constructor you can pass in a function like so:
ProgressChecker(Func<int,int,bool> checker)
That means you can pass a function into the constructor for ProgressChecker
public bool checker (int a, int b)
{
return a < b;
}
var t = new ProgressChecker(checker);
EDIT:
If you want to use the delegate, then in the ProgressChecker class, the constructor must take in that delegate type:
private delIsDone delIsDone;
public ProgressChecker(delIsDone delIsDone)
{
this.delIsDone = delIsDone;
}
You can the pass a delegate instance like so:
public class Program
{
public delegate bool delIsDone(int curState, int needState);
public static bool checkNumbers(int a, int b)
{
return a < b;
}
public static void Main(string[] args)
{
var t = new ProgressChecker(new delIsDone(checkNumbers));
// OR var t = new ProgressChecker(new delIsDone((a, b) => { return a < b; }));
}
}

You can also create Expression Trees, it is my snippet for it (it can be easly converted to your example)
//easy way
Expression<Action<int>> printExpr = (arg) => Console.WriteLine(arg);
printExpr.Compile()(10);
//hard way
ParameterExpression param = Expression.Parameter(typeof(int), "arg");
MethodCallExpression methodCall = Expression.Call
(
typeof(Console).GetMethod("WriteLine", new[]
{
typeof(int)
}
),
param
);
Expression.Lambda<Action<int>>(methodCall, param).Compile()(10); //execution
More information ca be gathered at Generating Dynamic Methods with Expression Trees

Related

Convert Expression<Action<T>> to Expression<Func<T>>

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.

Get expression arguments?

Ok, here is the problem:
int a = 111;
int b = 222;
Expression<Func<int>> expr = ()=> someClass.SomeWork(a) + b + 1;
As you see, there is 3 different arguments: someClass, a, b. They are all from another scope of execution, but one isn't. How I can get them? I mean, in general, I want only variables of outter scope.
For example, I want to use it like this:
var result = InvokeAndLog(expr);//this will invoke expression and print out everything I need from these arguments.
Ok, folks, I found answer myself. And here it is:
internal class Program
{
public static int Method1()
{
return new Random(0).Next(10000);
}
public class MyClass
{
private int var = 11111;
public int GetSome(int val)
{
return var * val;
}
}
private static void Main()
{
var clas = new MyClass();
int a = 111;
int b = 222;
Expression<Func<int>> expr = () => a * 2 - clas.GetSome(b) + b + 1 - Method1();
var result = InvokeAndLog(expr);
}
private static T InvokeAndLog<T>(Expression<Func<T>> expr)
{
var visitor = new ArgumentsVisitor();
visitor.Visit(expr);
Console.WriteLine("Inputs: {0}", string.Join(", ", visitor.Arguments));
return expr.Compile()();
}
}
The main class here is ExpressionVisitor descendant. I just overrided its member visitor and aggregated all members into single set:
public class ArgumentsVisitor : ExpressionVisitor
{
private readonly HashSet<MemberInfo> _all = new HashSet<MemberInfo>();
public IEnumerable<MemberInfo> Arguments
{
get { return _all; }
}
protected override Expression VisitMember(MemberExpression node)
{
_all.Add(node.Member);
return base.VisitMember(node);
}
}
Then I applyed visitor to expression and printed out all variables! Thanks, microsoft =)

How can i access the value of a local variable from within an expression tree

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.

Function pointers in C#

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.

How to convert delegate to object in C#?

I am using reflection class to invoke some methods which are on the some other dll.
And one of the methods' parameters are type of delegate.
And I want to invoke this methods by using reflection.
So I need to pass function parameters as object array, but I could not find anything about
how to convert delegate to object.
Thanks in advance
A delegate is an object. Just create the expected delegate as you would normally, and pass it in the parameters array. Here is a rather contrived example:
class Mathematician {
public delegate int MathMethod(int a, int b);
public int DoMaths(int a, int b, MathMethod mathMethod) {
return mathMethod(a, b);
}
}
[Test]
public void Test() {
var math = new Mathematician();
Mathematician.MathMethod addition = (a, b) => a + b;
var method = typeof(Mathematician).GetMethod("DoMaths");
var result = method.Invoke(math, new object[] { 1, 2, addition });
Assert.AreEqual(3, result);
}
Instances of delegates are objects, so this code works (C#3 style) :
Predicate<int> p = (i)=> i >= 42;
Object[] arrayOfObject = new object[] { p };
Hope it helps !
Cédric
Here's an example:
class Program
{
public delegate void TestDel();
public static void ToInvoke(TestDel testDel)
{
testDel();
}
public static void Test()
{
Console.WriteLine("hello world");
}
static void Main(string[] args)
{
TestDel testDel = Program.Test;
typeof(Program).InvokeMember(
"ToInvoke",
BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static,
null,
null,
new object[] { testDel });
}
}
I think this blog post:
C# Reflection - Dealing with Remote Objects
answers your question perfectly.
you can see a delegate as variable type "function". the delegate describes the parameters and return value for a matching function.
delegate void Foo(int a); // here a new delegate obj type Foo has been declared
the above example allows 'Foo' to be used as a data type, the only allowed object that can be matched with a variable of type Foo data type is a method with the same signature so:
void MyFunction(int x);
Foo D = MyFunction; // this is OK
void MyOtherFunction(string x);
Foo D = MyOtherFunction; // will yield an error since not same signature.
Once you have assigned a method to a delegate, you can invoke the method via the delegate:
int n = 1;
D( n ); // or D.Invoke( n );

Categories

Resources