namespace PickOverload;
class Program {
delegate string Formatter( object o );
string Show( double a ) { return a.ToString(); }
string Show( int a ) { return a.ToString(); }
string Format( Formatter f, object o ) { return f( o ); }
void SelectArgument() {
// error CS1503: Argument 1: cannot convert from 'method group' to 'Program.Formatter'
Format( Show, 1.234 );
}
void SelectDelegate() {
// error CS0123: No overload for 'Show' matches delegate 'Program.Formatter
Formatter x = this.Show;
}
void Run() {
SelectArgument();
SelectDelegate();
}
static void Main( string[] args ) {
new Program().Run();
}
}
Is there a C# syntax for picking one of the overloaded Show methods as argument for the Format method or for the delegate?
I'm not looking for a solution for the above sample, but for ways to pick one of multiple overloaded methods for delegates or method arguments.
Same problem here:
void Run() {
double f = 1.234;
Format( Show, f );
Formatter x = this.Show;
}
static void Main(string[] args ) {
new Program().Run();
}
You can do this with generics, for example:
internal delegate string Formatter<T>(T o);
internal static string Show(double a) => a.ToString();
internal static string Show(int a) => a.ToString();
internal static string Format<T>(Formatter<T> f, T o) => f(o);
static void Main(string[] args)
{
double f = 1.234;
Format(Show, f);
}
Related
The title is may be not clear enough, but I'll show you a short program in order to make you understand what I want to do:
Class Program
{
private static Obj A = new Obj(...);
private static void Function(AnyMethodOfMyObject() m)
{
object[] result = A.m();
...
}
static void main()
{
double a,b,c = 0;
string d = " ";
Function(MethodX(a,b,c));
Function(MethodY(d,a,b));
...
}
}
The methods will always return the same type which is an object[], but I don't have the same number/type of argument.
Thanks !
You can do this simply with a Func<object[]>:
class Program
{
private static Obj A = new Obj(...);
private static void Function(Func<object[]> m)
{
object[] result = m();
...
}
static void main()
{
double a,b,c = 0;
string d = " ";
Function(() => A.MethodX(a,b,c));
Function(() => A.MethodY(d,a,b));
...
}
}
Func<object[]> is a delegate (broadly, a reference to a method) which does not take any parameters, and which returns an array of objects. While MethodX takes 3 parameters (a,b,c), we can create a new anonymous method without doesn't take any parameters itself, and which just calls MethodX and passes in the values of a, b and c (they're captured at the point that we create this new anonymous method). This is what () => MethodX(a, b, c) does.
If you have different Obj instances and you want to control which one the method is called on, then use a Func<Obj, object[]>. This takes an Obj as a parameter, and returns an object[] as before.
class Program
{
private static Obj A = new Obj(...);
private static void Function(Func<Obj, object[]> m)
{
object[] result = m(A);
...
}
static void main()
{
double a,b,c = 0;
string d = " ";
Function(x => x.MethodX(a,b,c));
Function(x => x.MethodY(d,a,b));
...
}
}
I'm sorry if the title is unclear. Basically I want to DRY my code by moving a lot of repetitive error handling to one place.
I'm calling several methods, which all throw similar errors. Each takes different parameters, and returns different types. I'd like to be able to do something like this:
public class MyClass {
public static ErrorWrapper<Void> Method1(string s1, string s2) {
return Wrapper<Void>(System.Method1, s1, s2);
}
public static ErrorWrapper<string> Method2(string s) {
return Wrapper<string>(System.Method2, s);
}
public static ErrorWrapper<MyOtherClass> Method3(string s, int i) {
return Wrapper<MyOtherClass>(System.Method3, s, i)
}
private static ErrorWrapper<T> Wrapper<T>(Func f, /*parameters?*/) {
try {
return f(parameters);
} catch {
// Handle exceptions
}
}
I need to do this because I'm writing bindings for a language without exception handling, so using a error wrapping class is the only way to call standard library methods safely.
Unless I'm missing something here -
private static ErrorWrapper<T> Wrapper<T>(Func<T> f)
{
// implementation
}
Usage:
return Wrapper<string>(() => System.Method2(s));
return Wrapper<MyOtherClass>(() => System.Method3(s, I));
Here is my suggestion based on my understanding of what you are attempting. Unfortunately you must use a DynamicInvoke which is slow in order to check types at runtime when calling a general Delegate. You can't use void as a type argument to a generic, so I created a MyVoid class that I handle specially.
I updated my answer to reflect the System.Methods being actual methods, and not static fields, and so they must be cast when passed to Wrapper<> - C# has no way to convert a method to a general Delegate.
I have also added a type safe version but that requires creating a lot of boilerplate methods to handle the number of arguments, but it does eliminate a lot of casting and can call the delegate statically, which should be more efficient.
I accidentally had Method3 take two string parameters initially, and the non-type-safe version didn't have an error until called at run time. The type-safe version caught the mistake at compile time.
public class MyVoid { }
public class ErrorWrapper<T> {
public T Result;
public bool ValidResult;
public Exception Exception;
public ErrorWrapper(T res) {
ValidResult = true;
Result = res;
}
public ErrorWrapper(Exception e) {
Exception = e;
ValidResult = false;
}
public ErrorWrapper() { // void
ValidResult = true;
}
}
public class MyClass {
public static ErrorWrapper<MyVoid> Method1(string s1, string s2) => Wrapper<MyVoid>((Action<string, string>)System.Method1, s1, s2);
public static ErrorWrapper<string> Method2(string s) => Wrapper<string>((Func<string, string>)System.Method2, s);
public static ErrorWrapper<MyOtherClass> Method3(string s, int i) => Wrapper<MyOtherClass>((Func<string, int, MyOtherClass>)System.Method3, s, i);
private static ErrorWrapper<T> Wrapper<T>(Delegate f, params object[] p) {
try {
switch (default(T)) {
case MyVoid _:
f.DynamicInvoke(p);
return new ErrorWrapper<T>();
default:
return new ErrorWrapper<T>((T)f.DynamicInvoke(p));
}
}
catch (Exception e) {
// Handle exceptions
return new ErrorWrapper<T>(e);
}
}
}
public static class ErrorWrapper {
public static ErrorWrapper<T> New<T>(T res) => new ErrorWrapper<T>(res);
}
public class MyTypeSafeClass {
public static ErrorWrapper<MyVoid> Method1(string s1, string s2) => WrapperAction(System.Method1, s1, s2);
public static ErrorWrapper<string> Method2(string s) => WrapperFunc(System.Method2, s);
public static ErrorWrapper<MyOtherClass> Method3(string s, int i) => WrapperFunc(System.Method3, s, i);
private static ErrorWrapper<MyVoid> WrapperAction<T1, T2>(Action<T1, T2> f, T1 p1, T2 p2) {
try {
f(p1, p2);
return ErrorWrapper.New(default(MyVoid));
}
catch (Exception e) {
// Handle exceptions
return new ErrorWrapper<MyVoid>(e);
}
}
private static ErrorWrapper<TRes> WrapperFunc<T1, TRes>(Func<T1, TRes> f, T1 p1) {
try {
return ErrorWrapper.New(f(p1));
}
catch (Exception e) {
// Handle exceptions
return new ErrorWrapper<TRes>(e);
}
}
private static ErrorWrapper<TRes> WrapperFunc<T1, T2, TRes>(Func<T1, T2, TRes> f, T1 p1, T2 p2) {
try {
return ErrorWrapper.New(f(p1, p2));
}
catch (Exception e) {
// Handle exceptions
return new ErrorWrapper<TRes>(e);
}
}
}
How can I correct this error I'm having
TargetParameterCountException was unhandled by user code. Parameter count mismatch.
This is my code where it's happening
public static void InvokeMethod(string className, string methodName, string fileName)
{
var t = Type.GetType(className);
using (StreamReader f = new StreamReader("params.txt"))
{
t.GetMethod(methodName).Invoke(t.GetConstructor(Type.EmptyTypes).Invoke(new object[] { }), new object[] { f.ReadLine() });
}
}
This is the whole code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.IO;
class MyClass
{
private int i;
public double d;
private string s;
public bool b;
public MyClass()
{
i = 1;
d = 0.1;
s = "1";
b = true;
}
public void Method0()
{
Console.WriteLine("Method with no arguments, no return value.");
}
private int Method1(int arg0)
{
Console.WriteLine("The method returns int, int gets.");
return arg0;
}
private double Method2(int arg0, double arg1)
{
Console.WriteLine("Method returns a double, taking int and double.");
return arg1 * arg0;
}
public bool Method3(string arg0)
{
Console.WriteLine("Method returns a bool, accepts string");
return arg0.Length>10;
}
public bool Method3(string arg0,string arg1)
{
Console.WriteLine("The method takes two arguments string.");
return arg0 == arg1;
}
public static char Method4(string arg0)
{
Console.WriteLine("Method returns a char, accepts string. .");
Console.WriteLine(arg0);
return arg0[1];
}
public void Method5(int arg0, double arg1)
{
Console.WriteLine("arg1 = {0} arg2 = {1}.",arg0,arg1);
}
}
class MyTestClass
{
public static string[] GetMethodsWithStrParams(string className)
{
var t = Type.GetType(className);
List<string> res = new List<string>();
foreach (var method in t.GetMethods())
{
foreach (var param in method.GetParameters())
{
if (param.ParameterType == typeof(string))
{
res.Add(method.Name);
break;
}
}
}
return res.ToArray();
}
public static void InvokeMethod(string className, string methodName, string fileName)
{
var t = Type.GetType(className);
using (StreamReader f = new StreamReader("params.txt"))
{
t.GetMethod(methodName).Invoke(t.GetConstructor(Type.EmptyTypes).Invoke(new object[] { }),
new object[] { f.ReadLine() });
}
}
}
class Program
{
static void Main(string[] args)
{
string name = "MyClass";
foreach (var x in MyTestClass.GetMethodsWithStrParams(name))
{
Console.WriteLine(x);
}
MyTestClass.InvokeMethod("MyClass", "Method5", "params.txt");
Console.ReadKey(true);
}
}
Your InvokeMethod implementation always calls t.GetMethod(methodName).Invoke with two arguments, the first being the target instance on which the method is called, and second being the array of method arguments, which contains only one string (f.ReadLine()).
Then you use InvokeMethod to call MyClass.Method5 which takes two arguments, an int and a double. This obviously can't work, as myClass.Method5("some string") is syntactically incorrect, and this is what effectively happens. You can't expect that a string is a valid argument list for all MyClass methods, can you?
That is the cause of the error, but only you can decide how to fix it, as we don't know the greater context. You have to provide the correct number of parameters depending on the actual method being called.
Possible path to solution:
what are the arguments I want to provide to Method5?
where do I get them from?
how do I move them from wherever they are to the array I give to Invoke?
This should get you started, but no one can tell you exactly as you have only described the error, but not the real problem you are trying to solve with your code.
The error doesn't need any correction, it is correct. ;)
You are trying to call a method that takes two parameters with an array of parameters that only contains one item.
A parameter array that would work for that specific method would for example be:
new object[] { 0, 1.5 }
If you want your InvokeMethod method to work with methods that take different number of parameters with different types, you have to create different parameter arrays for each combination.
Is there any way to use DLR to reference a method in C#?
In dynamic languages like JavaScript or Python I could easily pass a method as an argument to another method. In C# being statically typed language, I either use Delegate type which needs lots of casting:
public static void AddMethod(Delegate del)
{
// implementation
}
and then use casting whenever I call this method
static void Main(string[] args)
{
AddMethod(new Func<object, bool>(Test));
}
public static bool Test(object obj)
{
return true;
}
Or, I need to define dozens of overloads to satisfy any method calls:
public static void AddMethod<TResult>(Func<TResult> method)
{
}
public static void AddMethod<T, TResult>(Func<T, TResult> method)
{
}
public static void AddMethod<T1, T2, TResult>(Func<T1, T2, TResult> method)
{
}
public static void AddMethod<T1, T2, T3, TResult>(Func<T1, T2, T3, TResult> method)
{
}
Is there any cleaner way to define an argument as a placeholder for all other methods? (I'm trying to avoid MethodInfo or other Reflection stuff here)
I was trying something like this:
public delegate dynamic DynamicDelegate(params dynamic[] args);
public static void AddMethod(DynamicDelegate method)
{
}
But the compiler doesn't seem to accept a statically typed method for a dynamically declared delegates!
Any other thoughts?
You can use a simple Action
void AddMethod(Action action) //or void AddMethod(Func<TResult> fxn)
{
}
and call as
AddMethod(()=>Test(obj));
or
AddMethod(()=>Test(obj1,obj2));
--EDIT--
AddMethod(() => Math.Max(1,3));
AddMethod(() => (int)Math.Sqrt(4));
AddMethod(() => new int[]{8,5,6}.Min())
void AddMethod(Func<int> fxn)
{
int i = fxn() * fxn(); // <---
}
Since .NET doesn't allow delegates with an unknown parameter syntax (this would approximate C void pointers, which is not something you want in a type-safe language), the closest thing that allows a variable argument list would be to pass an array of object arguments (i.e. object MyMethod(params object[] args)).
However, since this array is also an object reference, you can suffice with a single object reference:
object MyMethod(object arg))
The .NET framework also does this, see e.g. the ParameterizedThreadStart delegate)
So the basic idea is that you require that the user writes his code as a method that matches the above signature, and in turn it can receive any variable list of arguments of any type or size.
see below
Logger coreLogger;
Logger coreErrorLogger;
public Core()
{
PassByReference timestamp = new PassByReference(Timestamp);
coreLogger = Logger.GetLogger("LiTHiuM Core");
coreLogger.SetFormat("[{0}][LiTHiuM Core]: ", timestamp);
coreLogger.AddLogger(Log);
coreErrorLogger = Logger.GetLogger("LiTHiuM Core Error");
coreErrorLogger.SetFormat("[{0}][LiTHiuM Core (ERROR)]: ", timestamp);
coreErrorLogger.AddLogger(Error);
}
public string Timestamp(params dynamic[] args)
{
return DateTime.Now.ToString();
}
public delegate dynamic Reference(params dynamic[] args);
public class PassByReference
{
Reference reference;
public PassByReference(Reference reference)
{
this.reference = reference;
}
public override string ToString()
{
return this.reference().ToString();
}
}
public class Logger
{
static Dictionary<string, Logger> logFormatDict = new Dictionary<string, Logger>();
private List<LoggerDelegate> loggerDelegates = new List<LoggerDelegate>();
public static Logger GetLogger(string name)
{
if (logFormatDict.ContainsKey(name))
{
return logFormatDict[name];
}
else
{
var newLogFormat = new Logger(name, "");
logFormatDict.Add(name, newLogFormat);
return newLogFormat;
}
}
private event LoggerDelegate loggingEvent;
private Logger(string name, string format, params dynamic[] args)
{
this.Name = name;
this.format = format;
this.args = args;
}
public void AddLogger(LoggerDelegate logger)
{
if (!loggerDelegates.Contains(logger))
{
loggingEvent += logger;
loggerDelegates.Add(logger);
}
}
public void RemoveLogger(LoggerDelegate logger)
{
if (loggerDelegates.Contains(logger))
{
loggingEvent -= logger;
loggerDelegates.Remove(logger);
}
}
public void Log(string text, params dynamic[] args)
{
this.Invoke(String.Format(text, args));
}
public void Invoke(string text, params dynamic[] args)
{
loggingEvent.Invoke(this.ToString() + text, args);
}
public void SetFormat(string format, params dynamic[] args)
{
this.args = args;
this.format = format;
}
public string Name
{
get;
set;
}
string format;
dynamic[] args;
public override string ToString()
{
return String.Format(format, args);
}
}
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.