How to convert Func<T, TResult> to Func<T> - c#

I have Func<object, bool> myDelegate and
some variable like this:
object test = new object();
How can I pass myDelegate through to a method expecting a Func<bool> argument:
class FuncT
{
static void Main(string[] args)
{
object test = new object();
Func<object, bool> myDelegate = (x) => x != null;
// how to pass myDelegate to methodName so that it evaluates against 'test'?
methodName(myDelegate);
}
static void methodName(Func<bool> criteria)
{
Console.Out.WriteLine("Criteria: {0}", criteria());
}
}
As alternative, I can change the method to have signature like void methodName(object a, Func<object, bool> criteria) and call it methodName (test, myDelegate), but why? I already have test variable of object type, so I would like to tell myDelegate to use it inside the method, so that methodName would get only a delegate without parameters.

Related

How to call method with Func<string, T> as one of parameter

I have a class RemoteData like below,
public class RemoteData
{
public RemoteData(string Message, string IP)
{
this.IP = IP;
this.Message = Message;
}
public string IP;
public string Message;
}
Now I have a IObservable<T> method UdpStream like below,
public static IObservable<RemoteData> UdpStream(IPEndPoint endpoint, Func<string, RemoteData> processor)
{
return Observable.Using(() => new UdpClient(endpoint),
udpClient => Observable.Defer(() =>
udpClient.ReceiveAsync().ToObservable()).Repeat().Select(result => processor(Encoding.UTF8.GetString(result.Buffer))));
}
Now how to call UdpStream, how to pass Func parameter?
var stream = UdpStream(new IPEndPoint(IPAddress.Any, 514), 2nd Param);
Func<T, U> represents a delegate that takes a T parameter and returns U. You can initialize a Func<T, U> using a method reference that matches that signature, or using a lambda expression.
Using a Func<,> as parameter is a common idiom for a callback. For example, if you have a method similar to this:
public static void Method(Func<T, U> func)
{
// ...
}
We can expect that Method will call whaterver you pass in the func parameter. In fact, this happens in the code your present (the parameter Func<string, RemoteData> processor is called where it says processor(Encoding.UTF8.GetString(result.Buffer))).
Now, you have Func<string, RemoteData>, thus you need a method that takes string and returns RemoteData. For example:
public static RemoteData Example(string input)
{
// ...
}
// ...
var observable = UdpStream(endpoint, Example);

How to call Action<string, bool> from il generator

In this example code i am trying to invoke a anonymous action from il generator. I am not sure if and how i can load the reference to the delegate and how to call it.
I can do it if the OnFunctionCall is a static method not property.
public delegate void TestDelegate();
public static class ExampleOne
{
public static Action<string, bool> OnFunctionCall
=> (message, flag) => Console.WriteLine("Example");
}
public static class ExampleTwo
{
public static TType CreateDelegate<TType>(Action<string, bool> onFunctionCall)
where TType : class
{
var method = new DynamicMethod($"{Guid.NewGuid()}", typeof(void), Type.EmptyTypes, typeof(TType), true);
ILGenerator il = method.GetILGenerator();
// Emit some code that invoke unmanaged function ...
// loading the first string argument
il.Emit(OpCodes.Ldstr, method.Name);
// not sure here how to load boolean value to the stack
il.Emit(OpCodes.Ldc_I4_0);
// this line doesn't work
// example two has no idea about ExampleOne
// is it possible to load the reference of the Action<string, bool> to the stack and call it ?
il.Emit(OpCodes.Call, onFunctionCall.Method);
il.Emit(OpCodes.Ret);
return method.CreateDelegate(typeof(TestDelegate)) as TType;
}
}
public class Program
{
public static void Main(string[] args)
=> ExampleTwo
.CreateDelegate<TestDelegate>(ExampleOne.OnFunctionCall)
.Invoke();
}
You have to pass the information where the delegate you want to invoke is stored. The convenience way is to accept a MemberExpression, otherwise accepting a MemberInfowould work too. Have a look at your modified code:
public delegate void TestDelegate();
public static class ExampleOne
{
public static Action<string, bool> OnFunctionCall
=> (message, flag) => Console.WriteLine("OnFunctionCall");
public static Action<string, bool> OnFunctionCallField
= (message, flag) => Console.WriteLine("OnFunctionCallField");
}
public static class ExampleTwo
{
public static TType CreateDelegate<TType>(Expression<Func<object>> expression)
where TType : class
{
var body = expression.Body as MemberExpression;
if (body == null)
{
throw new ArgumentException(nameof(expression));
}
var method = new DynamicMethod($"{Guid.NewGuid()}", typeof(void), Type.EmptyTypes, typeof(TType), true);
ILGenerator il = method.GetILGenerator();
// Get typed invoke method and
// call getter or load field
MethodInfo invoke;
if (body.Member is PropertyInfo pi)
{
invoke = pi.PropertyType.GetMethod("Invoke");
il.Emit(OpCodes.Call, pi.GetGetMethod());
}
else if (body.Member is FieldInfo fi)
{
invoke = fi.FieldType.GetMethod("Invoke");
il.Emit(OpCodes.Ldsfld, fi);
}
else
{
throw new ArgumentException(nameof(expression));
}
il.Emit(OpCodes.Ldstr, method.Name);
il.Emit(OpCodes.Ldc_I4_0);
il.Emit(OpCodes.Callvirt, invoke);
il.Emit(OpCodes.Ret);
return method.CreateDelegate(typeof(TestDelegate)) as TType;
}
}
public class Program
{
public static void Main(string[] args)
{
ExampleTwo
.CreateDelegate<TestDelegate>(() => ExampleOne.OnFunctionCall)
.Invoke();
ExampleTwo
.CreateDelegate<TestDelegate>(() => ExampleOne.OnFunctionCallField)
.Invoke();
Console.ReadLine();
}
}
The code is running on .Net Core 2.0.

C# Lambda in MethodInfo invocation

I would like to invoke a lambda expression dynamically, but all I got is the methodInfo to do so.
Something like:
Magic.RegisterStaticPacketHandler<TestPacket>((a, b) => { /* Do Stuff */ });
Magic class:
public void RegisterStaticPacketHandler<T>(PacketReceivedHandler<T> handler) where T : Packet
{
//Remember the handler with: handler.GetMethodInfo()
}
And later on I would like to invoke this method. Because PacketReceivedHandler is a delegate, I can get the "MethodInfo" out of it. If I invoke this MethodInfo with just:
methodInfo.Invoke(obj, new object[] { packet, this });
I ofc receive an exception, that the given object (obj) doesn't fit.
Setting BindingFlags like "NonPublic | Instance | Static" doesnt help either.
UPDATE
PacketReceivedHandler looks as follows:
public delegate void PacketReceivedHandler<T>(T packet, Connection connection) where T : Packet;
And I save it in my Magic class:
private Dictionary<int, Tuple<MethodInfo, object>> id_methodInfo_object = new Dictionary<int, Tuple<MethodInfo, object>>();
MethodInfo = The delegate
object = Where the delegate comes from
id = UID for networking stuff
You have to save the Target of the delegate besides the method. The easiest is to directly store the whole delegate itself instead of MethodInfo. Something like this:
// Store any lambda or action or anything in their baseclass "Delegate":
Delegate act = new Action<int, int>((a, b) => Console.WriteLine(a + b));
// Dynamically invoke like this:
act.Method.Invoke(act.Target, new object[] {4, 9});
Full example:
class Program
{
private static List<Delegate> handlers = new List<Delegate>();
public static void RegisterHandler<T>(Action<T> del)
{
handlers.Add(del);
}
public static void InvokeHandlers(params object[] args)
{
foreach (var h in handlers)
{
h.Method.Invoke(h.Target, args);
}
}
static void Main(string[] args)
{
RegisterHandler((object a) => Console.WriteLine("#1:" + a));
RegisterHandler((object a) => Console.WriteLine("#2:" + a));
InvokeHandlers("foo");
InvokeHandlers(1234);
}
}
public void RegisterStaticPacketHandler<T>(PacketReceivedHandler<T> handler) where T : Packet
{
_methodInfo = handler.Method;
}
See details in MSDN

Is there a way to simplify this reflective delegate code in C#?

In this response, I came up with the following helper method that could be reused by different Task creators to convert events into task completion sources.
// Helper method
static Task<T> TaskFromEventHelper<T>(object target, string eventName, Func<TaskCompletionSource<T>, object> resultSetterFactory) {
var tcs = new TaskCompletionSource<T>();
var addMethod = target.GetType().GetEvent(eventName).GetAddMethod();
var delegateType = addMethod.GetParameters()[0].ParameterType;
var d = Delegate.CreateDelegate(delegateType, resultSetterFactory(tcs), "Invoke");
addMethod.Invoke(target, new object[] {d});
return tcs.Task;
}
// Empty events (Action style)
static Task TaskFromEvent(object target, string eventName) {
return TaskFromEventHelper(target, eventName, (Func<TaskCompletionSource<object>, object>)(tcs => (Action)(() => tcs.SetResult(null))));
}
// One-value events (Action<T> style)
static Task<T> TaskFromEvent<T>(object target, string eventName) {
return TaskFromEventHelper(target, eventName, (Func<TaskCompletionSource<T>, object>)(tcs => (Action<T>)(tcs.SetResult)));
}
// Two-value events (Action<T1, T2> or EventHandler style)
static Task<Tuple<T1, T2>> TaskFromEvent<T1, T2>(object target, string eventName) {
return TaskFromEventHelper(target, eventName, (Func<TaskCompletionSource<Tuple<T1, T2>>, object>)(tcs => (Action<T1, T2>)((t1, t2) => tcs.SetResult(Tuple.Create(t1, t2)))));
}
In each of the three examples I gave that use the helper method, there's a tcs.SetResult component, which makes me think there's a way to move that to the helper method too, which might perhaps simplify the signatures, so that perhaps the helper method would just have to accept a Func<?, T>, where that Func would take the output of the event and convert it to whatever tcs.SetResult takes.
i.e., I'm thinking there must be a way to create a helper so I can write it as
// Empty events (Action style)
static Task TaskFromEvent(object target, string eventName) {
return TaskFromEventHelper<object>(target, eventName, new Func<object>(() => null));
}
// One-value events (Action<T> style)
static Task<T> TaskFromEvent<T>(object target, string eventName) {
return TaskFromEventHelper<T>(target, eventName, new Func<T, T>(t => t));
}
// Two-value events (Action<T1, T2> or EventHandler style)
static Task<Tuple<T1, T2>> TaskFromEvent<T1, T2>(object target, string eventName) {
return TaskFromEventHelper<Tuple<T1, T2>>(target, eventName, new Func<T1, T2, Tuple<T1, T2>>(Tuple.Create));
}
, but that's why I don't know the ? in Func<?, T> above. This one for example needs ? to be two parameters. Could it be passed in as object somehow? I have a feeling it could be possible, but if so it needs some real reflection magic.
You can use Expression:
static Task<T> TaskFromEventHelper<T>(object target, string eventName, Delegate resultSetter)
{
var tcs = new TaskCompletionSource<T>();
var addMethod = target.GetType().GetEvent(eventName).GetAddMethod();
var delegateType = addMethod.GetParameters()[0].ParameterType;
var methodInfo = delegateType.GetMethod("Invoke");
var parameters = methodInfo.GetParameters()
.Select(a => Expression.Parameter(a.ParameterType))
.ToArray();
// building method, which argument count and
// their types are not known at compile time
var exp = // (%arguments%) => tcs.SetResult(resultSetter.Invoke(%arguments%))
Expression.Lambda(
delegateType,
Expression.Call(
Expression.Constant(tcs),
tcs.GetType().GetMethod("SetResult"),
Expression.Call(
Expression.Constant(resultSetter),
resultSetter.GetType().GetMethod("Invoke"),
parameters)),
parameters);
addMethod.Invoke(target, new object[] { exp.Compile() });
return tcs.Task;
}

Static dictionary containing delegates to instance methods

I have this method with a huge switch statement like this:
public bool ExecuteCommand(string command, string args)
{
bool result = false;
switch (command)
{
case "command1": result = Method1(args); break;
case "command2": result = Method2(args); break;
// etc.
}
return result;
}
private bool Method1(string args) {...}
Now I thought about replacing this with a dictionary of Func<> delegates so that I can eliminate the switch statement:
private Dictionary<string, Func<string, bool>> _commands = new ...;
public MyClass()
{
_commands.Add("command1", Method1);
// etc:
}
public bool ExecuteCommand(string command, string args)
{
return _commands[command](args);
}
The problem I see with this, is that a new Dictionary is instantiated and populated with each new instance of MyClass.
Is it possible to somehow make that Dictionary (containing delegates to instance methods) a static member, which would be initialized only once, in the static constructor?
E.g. something like this (does not work):
private static Dictionary<string, Func<string, bool>> _commands = new ...;
static MyClass()
{
// the following line will result in a compiler error:
// error CS0120: An object reference is required for the non-static field,
// method, or property 'MyClass.Method1(string, string)'
_commands.Add("command1", MyClass.Method1);
}
You can initialize it in the static constructor - but you'll need to create instances of MyClass, which may not be what you want, because I assume you want the command to execute "in the context of" the instance which Execute has been called on.
Alternatively, you can populate the dictionary with delegates which take an instance of MyClass as well, like this:
class MyClass
{
static Dictionary<string, Func<MyClass, string, bool>> commands
= new Dictionary<string, Func<MyClass, string, bool>>
{
{ "Foo", (#this, x) => #this.Foo(x) },
{ "Bar", (#this, y) => #this.Bar(y) }
};
public bool Execute(string command, string value)
{
return commands[command](this, value);
}
public bool Foo(string x)
{
return x.Length > 3;
}
public bool Bar(string x)
{
return x == "";
}
}
In theory I believe it should be doable without the lambda expression by creating an "open delegate", but it would need a bit more work using reflection. If you don't mind the ugliness and tiny performance penalty of the extra indirection, I think this approach should work quite well.

Categories

Resources