Creating a Func<object[], object> Delegate from MethodInfo - c#

After much research and searching on SO; I've failed to find an answer that encompasses my specific situation. I wish to add modding capabilities to my project; currently I use a 3rd-party C# API which can convert scripts written in a particular interpreted language (specifically the functions in these scripts) into C# delegates.
Is there a way to wrap all of the delegates I get from the 3rd party API, into the a generic Func Delegate? My thoughts (in code) follow...
//The goal signature for all 'imported' delegates
public delegate object GenericSignature(object[] args);
//A fictional example...
public class Program
{
public static void Main()
{
GenericSignature desiredFunc = GenerateFromArbitraryMethod(
Program.FictionalArbitraryMethod);
object retVal = desiredFunc(1, new object(), "If only this worked");
}
public static FictionalArbitraryMethod(int num, object stuff, string name)
{
//code from mod author would be here
}
}
//Attempt #1
//If my understanding about Delegate.CreateDelegate() is correct,
//this will not work...
public GenericSignature GenerateFromArbitraryMethod(Delegate d) {
MethodInfo mInfo = d.Method;
return (GenericSignature) Delegate.CreateDelegate(typeof(GenericSignature), mInfo);
}
//Attempt #2
//seems a bit... better?; I can do some validation, but how do I actually call the
//function represented by MethodInfo since it's signature is arbitrary?
public GenericSignature GenerateFromArbitraryMethod(Delegate d) {
MethodInfo mInfo = d.Method;
return delegate(object[] args) {
ParameterInfo[] pInfo = mInfo.GetParameters();
if(args.length != pInfo.length) {
throw new Exception("Argument count does not match");
}
for(int i = 0; i < args.length; i++) {
if(pInfo[i].ParameterType != args[i].GetType()) {
throw new Exception("Incorrect Type for argument");
}
}
//At a loss of how to do the following; fake psuedo-code follows
/*
Foreach(object currentArg in arg) {
d.AppendArgAndCast(currentArg);
}
return d.Call();
or...
return d(EachOrUnpackAndCast(args));
*/
};
}
Apologies if there are any errors in the syntax; I'm mainly trying to get across the concept of what I'm trying to achieve. Some additional notes:
Based on info from here; Unity supports .NET 3.5 features; so the solution I would use can leverage up to .NET 3.5.
It is ok if any suggested solution is 'slow/heavy' due to heavy use of reflection; as long as I can generate a delegate, which I can cache and just call many, many times (to amortize the initial delegate creation cost)
Delegate.DynamicInvoke() does not meet my project's performance requirements. My understanding is reflection APIs are used per DynamicInvoke() call. Using reflection one time to create the faster delegate is preferable.

You need to compile your own bytecode to cast each argument from object to the correct type.
If you can upgrade from .Net 2, Expression makes this very easy.
If not, you'll need to use ILGenerator, or a wrapper such as Sigil.

Related

Fast dynamic invoke between assemblies

Invoker.csproj -> Program.cs
namespace InvokeLibrary
{
public class Invoke
{
public static void Invoker(Delegate method, params object[] data)
{
for (int i = 0; i < 1000000; i++)
method.DynamicInvoke(data);
}
}
}
Caller.csproj -> Program.cs
using InvokeLibrary;
object obj = new A("Message from caller");
Invoke.Invoker(ToBeInvoked, obj);
void ToBeInvoked(A obj) =>
Console.WriteLine("A: " + obj.Message);
record A(string Message);
What would be the most efficient way for the library to invoke given delegates?
The library will call the same methods multiple times and the given data will always match the function's parameters.
Is there a way to improve performance or make the call less 'dynamic' trading for a slow overhead? Functions will be called many times so I don't mind if the first invoke will be slow.
I know about MethodInfo.Invoke but it takes too much memory to store in a list and Delegate.DynamicInvoke is too slow for my requirements
Check out the EfficientInvoker implementation from Tom Dupont which he claims is 10 times faster than Delegate.DynamicInvoke
GitHub path:
https://github.com/tdupont750/tact.net/blob/master/framework/src/Tact/Reflection/EfficientInvoker.cs
The Tests class contains examples of usage:
https://github.com/tdupont750/tact.net/blob/master/framework/tests/Tact.Tests/Reflection/EfficientInvokerTests.cs

Can I transform a Func<T> into an Expression<T>? [duplicate]

Going from a lambda to an Expression is easy using a method call...
public void GimmeExpression(Expression<Func<T>> expression)
{
((MemberExpression)expression.Body).Member.Name; // "DoStuff"
}
public void SomewhereElse()
{
GimmeExpression(() => thing.DoStuff());
}
But I would like to turn the Func in to an expression, only in rare cases...
public void ContainTheDanger(Func<T> dangerousCall)
{
try
{
dangerousCall();
}
catch (Exception e)
{
// This next line does not work...
Expression<Func<T>> DangerousExpression = dangerousCall;
var nameOfDanger =
((MemberExpression)dangerousCall.Body).Member.Name;
throw new DangerContainer(
"Danger manifested while " + nameOfDanger, e);
}
}
public void SomewhereElse()
{
ContainTheDanger(() => thing.CrossTheStreams());
}
The line that does not work gives me the compile-time error Cannot implicitly convert type 'System.Func<T>' to 'System.Linq.Expressions.Expression<System.Func<T>>'. An explicit cast does not resolve the situation. Is there a facility to do this that I am overlooking?
Ooh, it's not easy at all. Func<T> represents a generic delegate and not an expression. If there's any way you could do so (due to optimizations and other things done by the compiler, some data might be thrown away, so it might be impossible to get the original expression back), it'd be disassembling the IL on the fly and inferring the expression (which is by no means easy). Treating lambda expressions as data (Expression<Func<T>>) is a magic done by the compiler (basically the compiler builds an expression tree in code instead of compiling it to IL).
Related fact
This is why languages that push lambdas to the extreme (like Lisp) are often easier to implement as interpreters. In those languages, code and data are essentially the same thing (even at run time), but our chip cannot understand that form of code, so we have to emulate such a machine by building an interpreter on top of it that understands it (the choice made by Lisp like languages) or sacrificing the power (code will no longer be exactly equal to data) to some extent (the choice made by C#). In C#, the compiler gives the illusion of treating code as data by allowing lambdas to be interpreted as code (Func<T>) and data (Expression<Func<T>>) at compile time.
private static Expression<Func<T, bool>> FuncToExpression<T>(Func<T, bool> f)
{
return x => f(x);
}
What you probably should do, is turn the method around. Take in an Expression>, and compile and run. If it fails, you already have the Expression to look into.
public void ContainTheDanger(Expression<Func<T>> dangerousCall)
{
try
{
dangerousCall().Compile().Invoke();;
}
catch (Exception e)
{
// This next line does not work...
var nameOfDanger =
((MemberExpression)dangerousCall.Body).Member.Name;
throw new DangerContainer(
"Danger manifested while " + nameOfDanger, e);
}
}
public void SomewhereElse()
{
ContainTheDanger(() => thing.CrossTheStreams());
}
Obviously you need to consider the performance implications of this, and determine if it is something that you really need to do.
If you sometimes need an expression and sometimes need a delegate, you have 2 options:
have different methods (1 for each)
always accept the Expression<...> version, and just .Compile().Invoke(...) it if you want a delegate. Obviously this has cost.
NJection.LambdaConverter is a library that converts a delegate to an expression
public class Program
{
private static void Main(string[] args) {
var lambda = Lambda.TransformMethodTo<Func<string, int>>()
.From(() => Parse)
.ToLambda();
}
public static int Parse(string value) {
return int.Parse(value)
}
}
You can go the other way via the .Compile() method however - not sure if this is useful for you:
public void ContainTheDanger<T>(Expression<Func<T>> dangerousCall)
{
try
{
var expr = dangerousCall.Compile();
expr.Invoke();
}
catch (Exception e)
{
Expression<Func<T>> DangerousExpression = dangerousCall;
var nameOfDanger = ((MethodCallExpression)dangerousCall.Body).Method.Name;
throw new DangerContainer("Danger manifested while " + nameOfDanger, e);
}
}
public void SomewhereElse()
{
var thing = new Thing();
ContainTheDanger(() => thing.CrossTheStreams());
}
Expression<Func<T>> ToExpression<T>(Func<T> call)
{
MethodCallExpression methodCall = call.Target == null
? Expression.Call(call.Method)
: Expression.Call(Expression.Constant(call.Target), call.Method);
return Expression.Lambda<Func<T>>(methodCall);
}
JB Evain from the Cecil Mono team is doing some progress to enable this
http://evain.net/blog/articles/2009/04/22/converting-delegates-to-expression-trees
Change
// This next line does not work...
Expression<Func<T>> DangerousExpression = dangerousCall;
To
// This next line works!
Expression<Func<T>> DangerousExpression = () => dangerousCall();

Creating a Delegate from methodInfo in Mono 2.8.2

Hi I am trying to create a messenger in Mono 2.8.2 - the subset used by Unity3d. I thought it would be nifty to create a helper to auto subscribe methods to the messenger when they are decorated with a "subscribe" attribute.
I've been scratching my head over this and have read many of the other related stack questions without a solution to my problem. Frankly, I don't know if I am doing something wrong or if this is a bug in Mono.
foreach (var methodInfo in methods)
{
var attr = methodInfo.GetAttribute<SubscribeAttribute>();
if (attr == null)
continue;
var parmas = methodInfo.GetParameters();
if (parmas.Length != 1)
{
Debug.LogError("Subscription aborted. Invalid paramters.");
continue;
}
var type = parmas[0].ParameterType;
// Crashes here
// ArgumentException: method argument length mismatch
// I have tried many combinations..
// Direct typing of the message type and dynamic typing
var action = (Action<object>)Delegate.CreateDelegate(typeof(Action<object>), methodInfo);
// also does not work
// var dt = Expression.GetActionType(parmas.Select(o => o.ParameterType).ToArray());
// var action = Delegate.CreateDelegate(dt, methodInfo);
Subscribe(type, action, instance);
}
Any suggestions or work around would be appreciated.
Edit
The method signature looks like :
[Subscribe]
void OnMessage(object message){
// Hello World
}
Though, it was originally...
[Subscribe]
void OnTestMessage(TestMessage message){
// Hello World
}
It's a non-static method and you didn't provide a target object. Therefore Delegate.CreateDelegate will create an "open delegate" with an explicit this argument.
Because of the required this argument, it no longer matches the signature.

Passing a random method as a parameter?

Is there any way in C# to pass a random method as a parameter?
To explain my question:
I want to write a simple Logger-Tool that reports the entering and leaving of a method with the passed arguments an the class and method name:
The log file I'm aiming at:
ENTERING: ClassOfDoom::MethodOfDoom( arg1={1} [int], arg2={true} [bool] )
LEAVING: ClassOfDoom::MethodOfDoom RETURNING 1 [int]
The code I have in mind:
class ClassOfDoom {
// Remeber: MethodOfDoom is a _random_ method with _random_ arguments
public int MethodOfDoom(int arg1, bool arg2) {
Log.Entering(this, this.MethodOfDoom, arg1, arg2);
...
return Log.Returing(this, this.MethodOfDoom, 1);
}
}
Is there a way to achieve this? Or isn't C# as flexible as that?
Thanks in advance!
You can make your logging function take a MethodBase argument and use MethodBase.GetCurrentMethod to pass the current method info as an argument.
Then, in the logger, you could check its properties Name and DeclaringType to get the method information. Also, passing parameters is easy by declaring a params object[] args parameter in the logging function:
public static void Entering(object obj, MethodBase methodInfo,
params object[] args) {
Console.WriteLine("ENTERING {0}:{1}", methodInfo.DeclaringType.Name,
methodInfo.Name);
...
}
I'm not sure I entirely understand your question, but if you are trying to make a call to Log.Entering and Log.Returning inside an arbitrary (random) method and using the method's actual parameters, you should check out PostSharp. It will allow you to inject code in a method body and then do some work based on the reflected method information you get from the .NET framework (and the actual parameters passed to the method at runtime).
You could do it with Expression easily enough - it would look something like:
Log.Capture(() => this.MethodOfDoom(arg1, arg2));
Here's an example; I've been a bit lazy using Compile().DynamicInvoke() to read the arg-values - for real code I'd try to read it more directly:
using System;
using System.Diagnostics;
using System.Linq.Expressions;
class Program
{
DateTime MethodOfDoom(string s, int i)
{
return DateTime.Today;
}
public void RunTest()
{
int i =123;
Log.Capture(() => this.MethodOfDoom("abc", i));
}
static void Main()
{
new Program().RunTest();
}
}
static class Log
{
public static T Capture<T>(Expression<Func<T>> method)
{
MethodCallExpression mce = method.Body as MethodCallExpression;
if (mce == null) throw new InvalidOperationException(
"Method-call expected");
string name = mce.Method.Name;
try
{
int i = 0;
foreach(var param in mce.Method.GetParameters())
{
object argValue = Expression.Lambda(mce.Arguments[i++])
.Compile().DynamicInvoke();
Trace.WriteLine(param.Name + "=" + argValue, name);
}
Trace.WriteLine("ENTERING", name);
T result = method.Compile().Invoke();
Trace.WriteLine("EXITING: " + result, name);
return result;
}
catch (Exception ex)
{
Trace.WriteLine("EXCEPTION: " + ex, name);
throw;
}
}
}
If widely used in your code, this scenario is best implemented using Aspect Oriented Programming (AOP) techniques. There are different frameworks that can be used (such as Spring.NET AOP), which you can use in your .NET application. Here is a reference article that might help you get started:
http://www.developer.com/lang/article.php/10924_3795031_2
The referenced article gives you the logging enter/exit scenario as an example.
I have used PostSharp to do this very thing before.

C# - Can someone tell me why and where I should use delegates? [duplicate]

This question already has answers here:
Where do I use delegates? [closed]
(8 answers)
Closed 9 years ago.
I think I understand the concept of a delegate in C# as a pointer to a method, but I cant find any good examples of where it would be a good idea to use them. What are some examples that are either significantly more elegant/better with delegates or cant be solved using other methods?
The .NET 1.0 delegates:
this.myButton.Click += new EventHandler(this.MyMethod);
The .NET 2.0 delegates:
this.myOtherButton.Click += delegate {
var res = PerformSomeAction();
if(res > 5)
PerformSomeOtherAction();
};
They seem pretty useful. How about:
new Thread(new ThreadStart(delegate {
// do some worker-thread processing
})).Start();
What exactly do you mean by delegates? Here are two ways in which they can be used:
void Foo(Func<int, string> f) {
//do stuff
string s = f(42);
// do more stuff
}
and
void Bar() {
Func<int, string> f = delegate(i) { return i.ToString(); }
//do stuff
string s = f(42);
// do more stuff
}
The point in the second one is that you can declare new functions on the fly, as delegates. This can be largely replaced by lambda expressions,and is useful any time you have a small piece of logic you want to 1) pass to another function, or 2) just execute repeatedly. LINQ is a good example. Every LINQ function takes a lambda expression as its argument, specifying the behavior. For example, if you have a List<int> l then l.Select(x=>(x.ToString()) will call ToString() on every element in the list. And the lambda expression I wrote is implemented as a delegate.
The first case shows how Select might be implemented. You take a delegate as your argument, and then you call it when needed. This allows the caller to customize the behavior of the function. Taking Select() as an example again, the function itself guarantees that the delegate you pass to it will be called on every element in the list, and the output of each will be returned. What that delegate actually does is up to you. That makes it an amazingly flexible and general function.
Of course, they're also used for subscribing to events. In a nutshell, delegates allow you to reference functions, using them as argument in function calls, assigning them to variables and whatever else you like to do.
I primarily use the for easy asynch programming. Kicking off a method using a delegates Begin... method is really easy if you want to fire and forget.
A delegate can also be used like an interface when interfaces are not available. E.g. calling methods from COM classes, external .Net classes etc.
Events are the most obvious example. Compare how the observer pattern is implemented in Java (interfaces) and C# (delegates).
Also, a whole lot of the new C# 3 features (for example lambda expressions) are based on delegates and simplify their usage even further.
For example in multithread apps. If you want several threads to use some control, You shoul use delegates. Sorry, the code is in VisualBasic.
First you declare a delegate
Private Delegate Sub ButtonInvoke(ByVal enabled As Boolean)
Write a function to enable/disable button from several threads
Private Sub enable_button(ByVal enabled As Boolean)
If Me.ButtonConnect.InvokeRequired Then
Dim del As New ButtonInvoke(AddressOf enable_button)
Me.ButtonConnect.Invoke(del, New Object() {enabled})
Else
ButtonConnect.Enabled = enabled
End If
End Sub
I use them all the time with LINQ, especially with lambda expressions, to provide a function to evaluate a condition or return a selection. Also use them to provide a function that will compare two items for sorting. This latter is important for generic collections where the default sorting may or may not be appropriate.
var query = collection.Where( c => c.Kind == ChosenKind )
.Select( c => new { Name = c.Name, Value = c.Value } )
.OrderBy( (a,b) => a.Name.CompareTo( b.Name ) );
One of the benefits of Delegates is in asynchronous execution.
when you call a method asynchronously you do not know when it will finish executing, so you need to pass a delegate to that method that point to another method that will be called when the first method has completed execution. In the second method you can write some code that inform you the execution has completed.
Technically delegate is a reference type used to encapsulate a method with a specific signature and return type
Some other comments touched on the async world... but I'll comment anyway since my favorite 'flavor' of doing such has been mentioned:
ThreadPool.QueueUserWorkItem(delegate
{
// This code will run on it's own thread!
});
Also, a huge reason for delegates is for "CallBacks". Let's say I make a bit of functionality (asynchronously), and you want me to call some method (let's say "AlertWhenDone")... you could pass in a "delegate" to your method as follows:
TimmysSpecialClass.DoSomethingCool(this.AlertWhenDone);
Outside of their role in events, which your probably familiar with if you've used winforms or asp.net, delegates are useful for making classes more flexible (e.g. the way they're used in LINQ).
Flexibility for "Finding" things is pretty common. You have a collection of things, and you want to provide a way to find things. Rather than guessing each way that someone might want to find things, you can now allow the caller to provide the algorithm so that they can search your collection however they see fit.
Here's a trivial code sample:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Delegates
{
class Program
{
static void Main(string[] args)
{
Collection coll = new Collection(5);
coll[0] = "This";
coll[1] = "is";
coll[2] = "a";
coll[3] = "test";
var result = coll.Find(x => x == "is");
Console.WriteLine(result);
result = coll.Find(x => x.StartsWith("te"));
Console.WriteLine(result);
}
}
public class Collection
{
string[] _Items;
public delegate bool FindDelegate(string FindParam);
public Collection(int Size)
{
_Items = new string[Size];
}
public string this[int i]
{
get { return _Items[i]; }
set { _Items[i] = value; }
}
public string Find(FindDelegate findDelegate)
{
foreach (string s in _Items)
{
if (findDelegate(s))
return s;
}
return null;
}
}
}
Output
is
test
there isn't really anything delgates will solve that can't be solved with other methods, but they provide a more elegant solution.
With delegates, any function can be used as long as it has the required parameters.
The alternative is often to use a kind of custom built event system in the program, creating extra work and more areas for bugs to creep in
Is there an advantage to use a delegate when dealing with external calls to a database?
For example can code A :
static void Main(string[] args) {
DatabaseCode("test");
}
public void DatabaseCode(string arg) {
.... code here ...
}
Be improved in code B :
static void Main(string[] args) {
DatabaseCodeDelegate slave = DatabaseCode;
slave ("test");
}
public void DatabaseCode(string arg) {
.... code here ...
}
public delegate void DatabaseCodeDelegate(string arg);
It seems that this is subjective, but an area where there are strong conflicting view points?

Categories

Resources