There is as far as I know no way to interact with reference types in Expression trees. (e.g. nothing emits a stind.* or a ldind.* opcode).
I'm working on a bit of a rewriter to get around this annoyance. Since I'm building a new type that has the method body replaced with delegate invocations (to get around the fact that CompileToMethod can only do static methods that can't interact with new members). For by-ref and out parameters, I thought I'd replace their usages with StrongBox<T>.
So if I came across a method that has a signature that looks like this::
public class SomeClass
{
public virtual bool SomeMethod(string arg1,ref int arg2)
{
}
}
The override, the callbase method, and the delegate field I generate will look like this::
public class SomeClass<1> : SomeClass
{
private static bool SomeMethod<0>(
SomeClass target,string arg1,StrongBox<int> arg2)
{
return call target.SomeMethod(arg1,ref arg2.Value)
}
private Func<SomeClass,string,StrongBox<int>,bool> <0>SomeMethod;
public override bool SomeMethod(string arg1,ref int arg2)
{
StrongBox<int> box = new StrongBox<int>();
box.Value = arg2;
bool retVal = <0>SomeMethod.Invoke(this,arg1,box);
arg2 = box.Value;
return retVal;
}
}
However, this is quite a lot of code to perform this conversion, for each parameter it introduces a lot of complexity. It would be much easier when I perform the setting of box.Value = arg2, if I could do something like &box.Value = &arg2 that is assign it's address to the address of arg2 as it stands. That way when the delegate performs a mutation on the value field the changes are forwarded. Doing this means I don't need to have to have a variable to hold the return value, and I don't need to perform a reference value update.
Alternatively, if there is a way to perform assign-by-ref semantics with Expression trees, I'm all ears of course.
Not sure if I really understand but maybe this is a solution:
class Program
{
public class SomeClass
{
private readonly int _n;
public SomeClass(int n) { _n = n; }
public virtual bool SomeMethod(string arg1, ref int arg2) {
if (String.IsNullOrWhiteSpace(arg1)) return false;
arg2 += arg1.Length + _n;
return true;
}
}
private delegate bool SomeDelegate(SomeClass that, string arg1, ref int arg2);
static void Main(string[] args) {
var instance = Expression.Parameter(typeof (SomeClass), "that");
var arg1Param = Expression.Parameter(typeof(string), "arg1");
var arg2Param = Expression.Parameter(typeof (int).MakeByRefType(), "arg2");
var someMethodInfo = typeof (SomeClass).GetMethod("SomeMethod");
var lambda = Expression.Lambda<SomeDelegate>(Expression.Call(instance, someMethodInfo, arg1Param, arg2Param), instance, arg1Param, arg2Param);
var someDelegate =lambda.Compile();
var myClass = new SomeClass(2);
var arg1 = "yup";
var arg2 = 1;
var result = someDelegate(myClass, arg1, ref arg2);
if(arg2 != 6) throw new Exception("Bad!");
Console.WriteLine("works...");
}
}
The important bit I think is typeof (int).MakeByRefType() .
Related
How do I create a Dictionary where I can store functions?
Thanks.
I have about 30+ functions which can be executed from the user. I want to be able to execute the function this way:
private void functionName(arg1, arg2, arg3)
{
// code
}
dictionaryName.add("doSomething", functionName);
private void interceptCommand(string command)
{
foreach ( var cmd in dictionaryName )
{
if ( cmd.Key.Equals(command) )
{
cmd.Value.Invoke();
}
}
}
However, the function signature is not always the same, thus having different amount of arguments.
Like this:
Dictionary<int, Func<string, bool>>
This allows you to store functions that take a string parameter and return boolean.
dico[5] = foo => foo == "Bar";
Or if the function is not anonymous:
dico[5] = Foo;
where Foo is defined like this:
public bool Foo(string bar)
{
...
}
UPDATE:
After seeing your update it seems that you don't know in advance the signature of the function you would like to invoke. In .NET in order to invoke a function you need to pass all the arguments and if you don't know what the arguments are going to be the only way to achieve this is through reflection.
And here's another alternative:
class Program
{
static void Main()
{
// store
var dico = new Dictionary<int, Delegate>();
dico[1] = new Func<int, int, int>(Func1);
dico[2] = new Func<int, int, int, int>(Func2);
// and later invoke
var res = dico[1].DynamicInvoke(1, 2);
Console.WriteLine(res);
var res2 = dico[2].DynamicInvoke(1, 2, 3);
Console.WriteLine(res2);
}
public static int Func1(int arg1, int arg2)
{
return arg1 + arg2;
}
public static int Func2(int arg1, int arg2, int arg3)
{
return arg1 + arg2 + arg3;
}
}
With this approach you still need to know the number and type of parameters that need to be passed to each function at the corresponding index of the dictionary or you will get runtime error. And if your functions doesn't have return values use System.Action<> instead of System.Func<>.
However, the function signature is not
always the same, thus having different
amount of arguments.
Let's start with a few functions defined like this:
private object Function1() { return null; }
private object Function2(object arg1) { return null; }
private object Function3(object arg1, object arg3) { return null; }
You really have 2 viable options at your disposal:
1) Maintain type-safety by having clients call your function directly.
This is probably the best solution, unless you have very good reasons for breaking from this model.
When you talk about wanting to intercept function calls, it sounds to me like you're trying to re-invent virtual functions. There's a boat load of ways to get this sort of functionality out of the box, such as inheriting from a base class an overriding its functions.
It sounds to me like you want a class that's more of a wrapper than a derived instance of a base class, so do something like this:
public interface IMyObject
{
object Function1();
object Function2(object arg1);
object Function3(object arg1, object arg2);
}
class MyObject : IMyObject
{
public object Function1() { return null; }
public object Function2(object arg1) { return null; }
public object Function3(object arg1, object arg2) { return null; }
}
class MyObjectInterceptor : IMyObject
{
readonly IMyObject MyObject;
public MyObjectInterceptor()
: this(new MyObject())
{
}
public MyObjectInterceptor(IMyObject myObject)
{
MyObject = myObject;
}
public object Function1()
{
Console.WriteLine("Intercepted Function1");
return MyObject.Function1();
}
public object Function2(object arg1)
{
Console.WriteLine("Intercepted Function2");
return MyObject.Function2(arg1);
}
public object Function3(object arg1, object arg2)
{
Console.WriteLine("Intercepted Function3");
return MyObject.Function3(arg1, arg2);
}
}
2) OR map the input of your functions to a common interface.
This might work if all of your functions are related. For example, if you're writing a game, and all the functions do something to some part of the player or player's inventory. You'd end up with something like this:
class Interceptor
{
private object function1() { return null; }
private object function2(object arg1) { return null; }
private object function3(object arg1, object arg3) { return null; }
Dictionary<string, Func<State, object>> functions;
public Interceptor()
{
functions = new Dictionary<string, Func<State, object>>();
functions.Add("function1", state => function1());
functions.Add("function2", state => function2(state.arg1, state.arg2));
functions.Add("function3", state => function3(state.arg1, state.are2, state.arg3));
}
public object Invoke(string key, object state)
{
Func<object, object> func = functions[key];
return func(state);
}
}
Define the dictionary and add the function reference as the value, using System.Action as the type:
using System.Collections;
using System.Collections.Generic;
public class Actions {
public Dictionary<string, System.Action> myActions = new Dictionary<string, System.Action>();
public Actions() {
myActions ["myKey"] = TheFunction;
}
public void TheFunction() {
// your logic here
}
}
Then invoke it with:
Actions.myActions["myKey"]();
Hey, I hope this helps. What language are you coming from?
internal class ForExample
{
void DoItLikeThis()
{
var provider = new StringMethodProvider();
provider.Register("doSomethingAndGetGuid", args => DoSomeActionWithStringToGetGuid((string)args[0]));
provider.Register("thenUseItForSomething", args => DoSomeActionWithAGuid((Guid)args[0],(bool)args[1]));
Guid guid = provider.Intercept<Guid>("doSomethingAndGetGuid", "I don't matter except if I am null");
bool isEmpty = guid == default(Guid);
provider.Intercept("thenUseItForSomething", guid, isEmpty);
}
private void DoSomeActionWithAGuid(Guid id, bool isEmpty)
{
// code
}
private Guid DoSomeActionWithStringToGetGuid(string arg1)
{
if(arg1 == null)
{
return default(Guid);
}
return Guid.NewGuid();
}
}
public class StringMethodProvider
{
private readonly Dictionary<string, Func<object[], object>> _dictionary = new Dictionary<string, Func<object[], object>>();
public void Register<T>(string command, Func<object[],T> function)
{
_dictionary.Add(command, args => function(args));
}
public void Register(string command, Action<object[]> function)
{
_dictionary.Add(command, args =>
{
function.Invoke(args);
return null;
} );
}
public T Intercept<T>(string command, params object[] args)
{
return (T)_dictionary[command].Invoke(args);
}
public void Intercept(string command, params object[] args)
{
_dictionary[command].Invoke(args);
}
}
The following scenario would allow you to use a dictionary of elements to send in as input parameters and get the same as the output parameters.
First add the following line at the top:
using TFunc = System.Func<System.Collections.Generic.IDictionary<string, object>, System.Collections.Generic.IDictionary<string, object>>;
Then inside your class, define the dictionary as follows:
private Dictionary<String, TFunc> actions = new Dictionary<String, TFunc>(){
{"getmultipledata", (input) =>
{
//DO WORKING HERE
return null;
}
},
{"runproc", (input) =>
{
//DO WORKING HERE
return null;
}
}
};
This would allow you to run these anonymous functions with a syntax similar to this:
var output = actions["runproc"](inputparam);
Why not use params object[] list for method parameters and do some validation inside either your methods (or calling logic), It will allow for a variable number of parameters.
I've a generic class like
public class Foo<T> where T : Delegate {
private T nop;
public Foo(T nop) {
this.nop = nop;
}
public T BuildDelegateChain() {
if(chainAvailable) {
return Delegate.Combine(...) as T;
} else {
return nop;
}
}
....
}
So for each instance I have to call:
Foo<Action<int>> foo = new Foo<Action<int>>( _ =>{});
Foo<Action<int,int>> foo = new Foo<Action<int,int>>( (_,__) =>{});
Is there a way to get a default "No Operation" delegate matching the type T?
I'm looking for something to replace the constructor to a constructor without any argument. Something like:
...
public Foo() {
this.nop = Delegate.CreateNop(typeof(T));
}
...
You can create a no-op delegate dynamically using the Expression class. For delegates with return types, the no-op would have to return default(TReturn). Otherwise it just needs to be an empty block. We'll then cache the delegate so reflection only happens once.
using System.Linq;
using System.Linq.Expressions;
public static class DelegateHelper<T> where T : Delegate
{
public static T NoOp { get; } = BuildNoOpDelegate();
private static T BuildNoOpDelegate()
{
var invoke = typeof(T).GetMethod(nameof(Action.Invoke));
var paramTypes = invoke.GetParameters().Select(c => c.ParameterType);
// return default(TReturn) or default(Void)
var body = Expression.Default(invoke.ReturnType);
var lambda = Expression.Lambda<T>(
body,
paramTypes.Select(Expression.Parameter)
);
return lambda.Compile();
}
}
And then to use it:
public class Foo<T> where T : Delegate {
private T nop;
public Foo() {
nop = DelegateHelper<T>.NoOp;
}
}
Interestingly, this also works for delegates with out/ref parameters. In the case of out we don't need to do anything special to set the values before the method exits (which would be required with straight C#)--they keep their default values. For example, suppose a delegate with the following signature:
public delegate int MyDelegate(out int x, ref string y);
This code will compile and execute successfully:
var nop = DelegateHelper<MyDelegate>.NoOp;
string val = "hello";
int ret = nop(out int i, ref val);
Console.WriteLine(ret); // prints "0"
Console.WriteLine(i); // prints "0"
Console.WriteLine(val); // unchanged, prints "hello"
Now this is all probably a bit overkill, but it should answer your question. Alternatively you could just treat null as your no-op sentinel value and use whatever?.Invoke() instead.
I'm playing with Reflection and I would like to encapsulate a call to an instance method.
I always end up doing something like this:
methodInfo.Invoke(instance, parameters)
I wonder if there's any way to encapsulate it to something like call.Invoke(parameters), where the instance is implicit.
You can create a delegate that binds the instance.
You can do this either with the static Delegate.CreateInstance method or with the MethodInfo.CrateInstance method. The former relies on you knowing that the instance is actually a hidden first parameter to the method, so the latter may be a little more clear.
class Thing
{
int _Number;
public Thing(int number) { _Number = number; }
public int GetNumber() { return _Number; }
}
public static void Main()
{
Thing thingOne = new Thing(1);
Thing thingTwo = new Thing(2);
MethodInfo getter = typeof(Thing).GetMethod("GetNumber");
Func<int> getOne = (Func<int>)Delegate.CreateDelegate(typeof(Func<int>), thingOne, getter);
Func<int> getTwo = (Func<int>)getter.CreateDelegate(typeof(Func<int>), thingTwo);
Console.WriteLine(getOne());
Console.WriteLine(getTwo());
}
Why not simply this:
public class MethodInvoker
{
private MethodInfo _method;
private object _target;
public MethodInvoker(MethodInfo method, object target)
{
_method = method;
_target = target;
}
public object Invoke(params object[] parameters) => _method.Invoke(_target, parameters);
}
...
string s = "Hello";
var invoker = new MethodInvoker(s.GetType().GetMethod("Substring",new Type[] { typeof(int), typeof(int) }), s);
Console.WriteLine(invoker.Invoke(1,3));
You might use generics for type safety on the target or return type.
I have a client application that uses classes (and enums) from an external dll which is loaded at runtime and reflected. I know what methods I am expecting to find in the dll and what I am expecting its enums to be called.
I would like to create a delegate that I can use in the client application and which is created from the reflected method at runtime. This approach works when the delegate just has "standard" types, but how can I get this to work if the dll method takes an enum? I can't declare the enum in the delegate as an object since it's a value type, trying the Enum or int does not seem to work either. Is there a way around this? Any help gratefully received!
// e.g. external code
namespace test2
{
public static class test2
{
public static int calc(int a, int b, testEnum c)
{
if (c == testEnum.add) return a + b;
else return a - b;
}
public static int add(int a, int b)
{
return a + b;
}
}
public enum testEnum
{
add, subtract
}
}
// my client code
namespace test1
{
public class TestClient
{
private static Assembly _assembly;
public static void SetUp()
{
const string externalDll = ".../test2.dll";
Assembly assembly = Assembly.LoadFrom(externalDll);
AppDomain.CurrentDomain.Load(assembly.GetName());
_assembly = assembly;
}
private delegate int _add(int a, int b);
private _add add;
private delegate int _calc(int a, int b, ??? c); // nothing works here
private _calc calc;
public void Run()
{
SetUp();
add = GetExpectedFunction<_add>("add");
int three = add(1, 2); // OK
calc = GetExpectedFunction<_calc>("calc"); // not OK
// intended usage
var reflectedEnum = ReflectMe("testEnum", "add");
int threeAgain = calc(1, 2, reflectedEnum);
}
public static T GetExpectedFunction<T>(string functionName) where T : class
{
try
{
if (!typeof(T).IsSubclassOf(typeof(Delegate))) throw new ApplicationException("GetExpectedFunction must return a delegate!");
var foundMethod = _assembly.GetType("test2.test2").GetMethod(functionName, BindingFlags.Public | BindingFlags.Static);
return (T)(object)Delegate.CreateDelegate(typeof(T), foundMethod);
}
catch (Exception e)
{
// "Error binding to target method!"
}
}
}
}
You can bind a delegate with object type to a method taking an enum by creating, at runtime, a dynamic method call with LINQ Expression, and adding data conversions for parameters whose types don't match:
public static T GetExpectedFunction<T>(string functionName) where T : class {
try {
if (!typeof(T).IsSubclassOf(typeof(Delegate))) throw new ApplicationException("GetExpectedFunction must return a delegate!");
var foundMethod = Type.GetType("test2.test2").GetMethod(functionName, BindingFlags.Public | BindingFlags.Static);
var inv = typeof(T).GetMethod("Invoke");
var parameters = inv.GetParameters().Zip(foundMethod.GetParameters(), (a, b) => new {
PassedIn = a.ParameterType
, Reflected = b.ParameterType
, Parameter = Expression.Parameter(a.ParameterType)
}).ToList();
if (parameters.All(p => p.PassedIn == p.Reflected)) {
// Bind directly
return (T)(object)Delegate.CreateDelegate(typeof(T), foundMethod);
}
var call = Expression.Call(foundMethod, parameters.Select(
p => p.PassedIn==p.Reflected
? (Expression)p.Parameter
: Expression.Convert(p.Parameter, p.Reflected)
));
return (T) (object) Expression.Lambda(typeof(T), call, parameters.Select(p => p.Parameter)).Compile();
} catch (Exception e) {
// "Error binding to target method!"
return null;
}
}
This implementation pairs up types from the reflected and the delegate methods (see parameters variable), and creates ParameterExpression objects for types that come from the delegate. Then it checks if all parameter types match up (the parameters.All(...) part). This is an optimization for situations when conversions are unnecessary.
If at least one conversion is necessary, the code creates a method call that substitutes the original parameter expressions with conversion expressions where types do not match up, creates a lambda of the requested delegate type, compiles it, and returns it to the caller.
For your code this dynamic method would look like this:
int dynamic_method(int a, int b, object c) {
return test2.test2(a, b, (testEnum)c);
}
There is one solution, you have to create faked Enum (it will be better if you create the exact enum), then you will pass as integer like this:
private delegate int _add(int a, int b);
private _add add;
private delegate int _calc(int a, int b, FakedEnum c); // faked enum here
private _calc calc;
public enum FakedEnum
{
}
public void Run()
{
SetUp();
add = GetExpectedFunction<_add>("add");
int three = add(1, 2); // OK
calc = GetExpectedFunction<_calc>("calc"); // it will be ok
var result= calc(4, 6, (FakedEnum)0);
// intended usage
// var reflectedEnum = ReflectMe("testEnum", "add");
//int threeAgain = calc(1, 2, reflectedEnum);
}
Use dynamic keyword to declare your delegate parameter:
private delegate int _calc(int a, int b, dynamic c);
How do I create a Dictionary where I can store functions?
Thanks.
I have about 30+ functions which can be executed from the user. I want to be able to execute the function this way:
private void functionName(arg1, arg2, arg3)
{
// code
}
dictionaryName.add("doSomething", functionName);
private void interceptCommand(string command)
{
foreach ( var cmd in dictionaryName )
{
if ( cmd.Key.Equals(command) )
{
cmd.Value.Invoke();
}
}
}
However, the function signature is not always the same, thus having different amount of arguments.
Like this:
Dictionary<int, Func<string, bool>>
This allows you to store functions that take a string parameter and return boolean.
dico[5] = foo => foo == "Bar";
Or if the function is not anonymous:
dico[5] = Foo;
where Foo is defined like this:
public bool Foo(string bar)
{
...
}
UPDATE:
After seeing your update it seems that you don't know in advance the signature of the function you would like to invoke. In .NET in order to invoke a function you need to pass all the arguments and if you don't know what the arguments are going to be the only way to achieve this is through reflection.
And here's another alternative:
class Program
{
static void Main()
{
// store
var dico = new Dictionary<int, Delegate>();
dico[1] = new Func<int, int, int>(Func1);
dico[2] = new Func<int, int, int, int>(Func2);
// and later invoke
var res = dico[1].DynamicInvoke(1, 2);
Console.WriteLine(res);
var res2 = dico[2].DynamicInvoke(1, 2, 3);
Console.WriteLine(res2);
}
public static int Func1(int arg1, int arg2)
{
return arg1 + arg2;
}
public static int Func2(int arg1, int arg2, int arg3)
{
return arg1 + arg2 + arg3;
}
}
With this approach you still need to know the number and type of parameters that need to be passed to each function at the corresponding index of the dictionary or you will get runtime error. And if your functions doesn't have return values use System.Action<> instead of System.Func<>.
However, the function signature is not
always the same, thus having different
amount of arguments.
Let's start with a few functions defined like this:
private object Function1() { return null; }
private object Function2(object arg1) { return null; }
private object Function3(object arg1, object arg3) { return null; }
You really have 2 viable options at your disposal:
1) Maintain type-safety by having clients call your function directly.
This is probably the best solution, unless you have very good reasons for breaking from this model.
When you talk about wanting to intercept function calls, it sounds to me like you're trying to re-invent virtual functions. There's a boat load of ways to get this sort of functionality out of the box, such as inheriting from a base class an overriding its functions.
It sounds to me like you want a class that's more of a wrapper than a derived instance of a base class, so do something like this:
public interface IMyObject
{
object Function1();
object Function2(object arg1);
object Function3(object arg1, object arg2);
}
class MyObject : IMyObject
{
public object Function1() { return null; }
public object Function2(object arg1) { return null; }
public object Function3(object arg1, object arg2) { return null; }
}
class MyObjectInterceptor : IMyObject
{
readonly IMyObject MyObject;
public MyObjectInterceptor()
: this(new MyObject())
{
}
public MyObjectInterceptor(IMyObject myObject)
{
MyObject = myObject;
}
public object Function1()
{
Console.WriteLine("Intercepted Function1");
return MyObject.Function1();
}
public object Function2(object arg1)
{
Console.WriteLine("Intercepted Function2");
return MyObject.Function2(arg1);
}
public object Function3(object arg1, object arg2)
{
Console.WriteLine("Intercepted Function3");
return MyObject.Function3(arg1, arg2);
}
}
2) OR map the input of your functions to a common interface.
This might work if all of your functions are related. For example, if you're writing a game, and all the functions do something to some part of the player or player's inventory. You'd end up with something like this:
class Interceptor
{
private object function1() { return null; }
private object function2(object arg1) { return null; }
private object function3(object arg1, object arg3) { return null; }
Dictionary<string, Func<State, object>> functions;
public Interceptor()
{
functions = new Dictionary<string, Func<State, object>>();
functions.Add("function1", state => function1());
functions.Add("function2", state => function2(state.arg1, state.arg2));
functions.Add("function3", state => function3(state.arg1, state.are2, state.arg3));
}
public object Invoke(string key, object state)
{
Func<object, object> func = functions[key];
return func(state);
}
}
Define the dictionary and add the function reference as the value, using System.Action as the type:
using System.Collections;
using System.Collections.Generic;
public class Actions {
public Dictionary<string, System.Action> myActions = new Dictionary<string, System.Action>();
public Actions() {
myActions ["myKey"] = TheFunction;
}
public void TheFunction() {
// your logic here
}
}
Then invoke it with:
Actions.myActions["myKey"]();
Hey, I hope this helps. What language are you coming from?
internal class ForExample
{
void DoItLikeThis()
{
var provider = new StringMethodProvider();
provider.Register("doSomethingAndGetGuid", args => DoSomeActionWithStringToGetGuid((string)args[0]));
provider.Register("thenUseItForSomething", args => DoSomeActionWithAGuid((Guid)args[0],(bool)args[1]));
Guid guid = provider.Intercept<Guid>("doSomethingAndGetGuid", "I don't matter except if I am null");
bool isEmpty = guid == default(Guid);
provider.Intercept("thenUseItForSomething", guid, isEmpty);
}
private void DoSomeActionWithAGuid(Guid id, bool isEmpty)
{
// code
}
private Guid DoSomeActionWithStringToGetGuid(string arg1)
{
if(arg1 == null)
{
return default(Guid);
}
return Guid.NewGuid();
}
}
public class StringMethodProvider
{
private readonly Dictionary<string, Func<object[], object>> _dictionary = new Dictionary<string, Func<object[], object>>();
public void Register<T>(string command, Func<object[],T> function)
{
_dictionary.Add(command, args => function(args));
}
public void Register(string command, Action<object[]> function)
{
_dictionary.Add(command, args =>
{
function.Invoke(args);
return null;
} );
}
public T Intercept<T>(string command, params object[] args)
{
return (T)_dictionary[command].Invoke(args);
}
public void Intercept(string command, params object[] args)
{
_dictionary[command].Invoke(args);
}
}
The following scenario would allow you to use a dictionary of elements to send in as input parameters and get the same as the output parameters.
First add the following line at the top:
using TFunc = System.Func<System.Collections.Generic.IDictionary<string, object>, System.Collections.Generic.IDictionary<string, object>>;
Then inside your class, define the dictionary as follows:
private Dictionary<String, TFunc> actions = new Dictionary<String, TFunc>(){
{"getmultipledata", (input) =>
{
//DO WORKING HERE
return null;
}
},
{"runproc", (input) =>
{
//DO WORKING HERE
return null;
}
}
};
This would allow you to run these anonymous functions with a syntax similar to this:
var output = actions["runproc"](inputparam);
Why not use params object[] list for method parameters and do some validation inside either your methods (or calling logic), It will allow for a variable number of parameters.