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);
}
}
Related
I have a method in C# which receives a generic type as argument:
private void DoSomething<T>(T param)
{
//...
}
I need to perform different things depending on what type is param of. I know I can achieve it with several if sentences, like this:
private void DoSomething<T>(T param)
{
if (param is TypeA)
{
// do something specific to TypeA case
} else if (param is TypeB)
{
// do something specific to TypeB case
} else if ( ... )
{
...
}
// ... more code to run no matter the type of param
}
Is there a better way of doing this? Maybe with switch-case or another approach that I'm not aware of?
Just use overloading instead of generics.
If project/logic structure allows it would be nice to move DoSomething into T and describe it with IDoSomething interface. This way you can write:
private void DoSomething<T>(T param) where T:IDoSomething
{
param.DoSomething()
}
If that's not an option then you can setup dictionary of rules
var actionsByType = new Dictionary<Type, Action<T /*if you neeed that param*/>(){
{ Type1, DoSomething1 },
{ Type2, DoSomething2 },
/..
}
and in your method you can call:
private void DoSomething<T>(T param){
//some checks if needed
actionsByType[typeof(T)](param/*if param needed*/);
}
You can create a specific method for a particular type.
private void DoSomething<T>(T param)
{
//...
}
private void DoSomething(int param) { /* ... */ }
private void DoSomething(string param) { /* ... */ }
As mentioned before if its a simple case use overloading. Anything stranger you can adapt this (its quick and dirty apologies).
class Program
{
interface IDoSomething<T>
{
void DoSomething(T param);
}
class Test : IDoSomething<int>, IDoSomething<string>
{
public void DoSomething(int param)
{
}
public void DoSomething(string param)
{
}
}
static void Main(string[] args)
{
DoSomething(4);
}
static void DoSomething<T>(T param)
{
var test = new Test();
var cast = test as IDoSomething<T>;
if (cast == null) throw new Exception("Unhandled type");
cast.DoSomething(param);
}
}
I have a class called Test which has a constructor to accept Action<T> and the other one accepts Func<T,T>. Please see the below snippet.
public class Test<T>
{
//constructors
public Test() { }
public Test(Action<T> action) { }
public Test(Func<T, T> action) { }
//methods with same signature of constructor
public void MyMethod1(Action<T> action) { }
public void MyMethod2(Func<T, T> action) { }
}
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Test<string> t1 = new Test<string>(this.MyMethod1);
Test<string> t2 = new Test<string>(this.MyMethod2);
Test<string> t = new Test<string>();
t.MyMethod1(MyMethod1);
t.MyMethod2(MyMethod2);
}
public void MyMethod1(string value) { }
public string MyMethod2(string value) { return string.Empty; }
}
But below lines throws an ambiguous call error
Test<string> t1 = new Test<string>(this.MyMethod1);
Test<string> t2 = new Test<string>(this.MyMethod2);
and the interesting point is, I have two methods with the same signature of my Test class constructor which not throwing any ambiguous error
Test<string> t = new Test<string>();
t.MyMethod1(MyMethod1);
t.MyMethod2(MyMethod2);
Could anyone please help me to identify and fix the issue.
The return value of a method is not part of its signature. Only the parameters are considered. Hence, the compiler cannot distinguish between Action<T> and Func<T,T>. A detailed explanation and workarounds can be found in this StackOverflow question
You can try renaming the parameters for each of your constructors like so:
public class Test<T>
{
public Test() { }
public Test(Action<T> action) { }
public Test(Func<T,T> function) { }
}
So when you instantiate your class you can specify the name of the parameter like so:
var objectWithAction = new Test<string>(action: Method1);
var objectWithFunction = new Test<string>(function: Method2);
Fact
method / constructor overloading can recognize the correct method by the parameter types but does not include the return type.
Reason
And since in both of the mentioned constructor calls in the question the parameter is of type MethodGroup so the compiler is unable to determine the correct overload. secondly calls to the method are successful as that in not an overloading scenario.
Resolution
here are the possible options to solve the issue
wrapping the method call into an anonymous method call and let the implicit conversion to distinguish themselves.
Test<string> t1 = new Test<string>(s => this.MyMethod1(s));
Test<string> t2 = new Test<string>(s => { return this.MyMethod2(s); });
result
Alternate approach
other option is to explicitly cast the method group
Test<string> t1 = new Test<string>((Action<string>)this.MyMethod1);
Test<string> t2 = new Test<string>((Func<string, string>)this.MyMethod2);
this is bit longer then the first approach if parameters are less
here a working console application sample
class Program
{
static void Main(string[] args)
{
Test<string> t1 = new Test<string>(action: MyMethod1);
Test<string> t2 = new Test<string>(function: MyMethod2);
Test<string> t = new Test<string>();
t.MyMethod1(MyMethod1);
t.MyMethod2(MyMethod2);
}
public static void MyMethod1(string value)
{
Console.WriteLine("my method1 {0}", value);
}
public static string MyMethod2(string value)
{
Console.WriteLine("my method2 {0}", value);
return string.Empty;
}
}
public class Test<T>
{
//constructors
public Test() { }
public Test(Action<T> action)
{
object args = "action";
action.Invoke((T)args); // here you should invoke the method in order to execute it
}
public Test(Func<T, T> function)
{
object args = "function";
function.Invoke((T)args);
}
//methods with same signature of constructor
public void MyMethod1(Action<T> action)
{
object args = "Method 3";
action.Invoke((T)args);
}
public void MyMethod2(Func<T, T> action)
{
object args = "Method 4";
action.Invoke((T)args);
}
}
hope it will help you
regards
In order to explain my problem here is an example
namespace CheckAbstarct
{
class Program
{
static void Main(string[] args)
{
myAbstarctClass mac1 = ObjectFactory.ObjectCreator("aaa");
myAbstarctClass mac2 = ObjectFactory.ObjectCreator("bbb");
mac1.changeMyString();
mac2.changeMyString();
string myString = (string)mac2.returnMyObject();
DateTime myObject = (DateTime) mac1.returnMyObject();
object obj1 = mac1.returnMyObject();
object obj2 = mac2.returnMyObject();
myMethod(obj1); //---> This is not compiling
myMethod(obj2); //---> This is not compiling
myMethod(myString); //---> works fine
myMethod(myObject); //---> works fine
Console.ReadKey();
}
public static void myMethod(DateTime dt)
{
}
public static void myMethod(string st)
{
}
}
abstract class myAbstarctClass
{
protected string mMyString;
public myAbstarctClass()
{
mMyString = "myAbstarctClass ";
}
public abstract void changeMyString();
public abstract object returnMyObject();
}
class MyNewAbstractClass1 : myAbstarctClass
{
DateTime mObject;
public MyNewAbstractClass1(string myString)
{
mMyString = myString;
mObject = new DateTime().Date;
}
public override void changeMyString()
{
mMyString += " MyNewAbstractClass1";
Console.WriteLine(mMyString);
}
public override object returnMyObject()
{
return mObject;
}
}
class MyNewAbstractClass2 : myAbstarctClass
{
string mString;
public MyNewAbstractClass2(string myString)
{
mMyString = myString;
mString = mMyString;
}
public override void changeMyString()
{
mMyString += " MyNewAbstractClass2";
Console.WriteLine(mMyString);
}
public override object returnMyObject()
{
return mString;
}
}
static class ObjectFactory
{
public static myAbstarctClass ObjectCreator(string myString)
{
switch (myString)
{
case "aaa":
return new MyNewAbstractClass1(myString);
case "bbb":
return new MyNewAbstractClass2(myString);
default:
return null;
}
}
}
}
My problem is that in Main() I don't know what type the returnMyObject() method returns so I can't send it to MyMethod. Is there a way to cast the objects ??
Because in your design of returnMyObject() you went back to the most common object references, you will have to find out in runtime:
if (obj1 is string)
myMethod((string)obj1); //--->cast it
else if (obj1 is DateTime)
myMethod((DateTime) obj1);
You could check the object's type at runtime:
public static void myMethod(Object o)
{
if (o is DateTime)
myMethod((DateTime)o);
else if (o is string)
myMethod((string)o);
}
Although in your case, you might just as well pass a myAbstarctClass instance to myMethod, and then call returnMyObject() there.
You can either use dynamic feature from C# 4.0 or change design to utilize some kind of double dispatch technique
dynamic obj1 = mac1.returnMyObject();
dynamic obj2 = mac2.returnMyObject();
Use Polymorphism mechanisms so you don't need to know the type of object.
Make myMethod an abstract method of myAbstarctClass and provide implementations in both MyNewAbstractClass1 and MyNewAbstractClass2.
Modify myAbstractClass1.returnMyObject() to return myAbstarctClass (not object).
The test code in Main can then be written:
...
myAbstarctClass obj1 = mac1.returnMyObject();
myAbstarctClass obj2 = mac2.returnMyObject();
obj1.myMethod(); // calls MyNewAbstractClass1.myMethod()
// no if statement required!
obj2.myMethod(); // calls MyNewAbstractClass2.myMethod()
// no if statement required!
Console.ReadKey();
Edit: This can be further simplified, since the returnMyObject() methods are no longer necessary - they just return the object you already have. The test code is now simply:
mac1.myMethod();
mac2.myMethod();
// etc...
Console.ReadKey();
No, you have to either create switch with all possibilities, or something like Dictionary<Type, Delegate>
or you can just make myMethod(object obj)
it's called Multiple dispatch (http://en.wikipedia.org/wiki/Multiple_dispatch) and there are some libraries that can do it
Since you seem to be using your class as a container for a type (eg. DateTime, string), perhaps Generics would a be better choice than Inheritance:
namespace CheckAbstract
{
class Program
{
static void Main(string[] args)
{
myTemplateClass<DateTime> mac1 = new myTemplateClass<DateTime>(new DateTime().Date);
myTemplateClass<string> mac2 = new myTemplateClass<string>("cat dog");
mac1.changeMyString();
mac2.changeMyString();
string myString = (string)mac2.returnMyObject();
DateTime myObject = (DateTime) mac1.returnMyObject();
myMethod<string>(myString);
myMethod<DateTime>(myObject);
Console.ReadKey();
}
public static void myMethod<T>(T obj)
{
}
}
class myTemplateClass<T>
{
T mObject;
string mMyString;
public myTemplateClass(T init)
{
mMyString = init.ToString();
mObject = init;
}
public void changeMyString()
{
mMyString += " " + mObject.ToString();
Console.WriteLine(mMyString);
}
public T returnMyObject()
{
return mObject;
}
}
}
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.
Assume we have legacy classes, that can't be modified:
class Foo
{
public void Calculate(int a) { }
}
class Bar
{
public void Compute(int a) {}
}
I want to write a helper with such signature:
void Calc(object obj, int a);
Notice, that the first argument is of type 'object'. The test code should be some like this:
ExampleX.Calc((object)new Foo(), 0);
ExampleX.Calc((object)new Bar(), 0);
The question is, what implementation you can imagine in addition to these:
// Using If/then
class Example1
{
public static void Calc(object obj, int a)
{
if (obj is Foo)
((Foo)obj).Calculate(a);
else if (obj is Bar)
((Bar)obj).Compute(a);
}
}
// Using reflection
class Example2
{
private static Dictionary<Type, MethodInfo> _methods = new Dictionary<Type, MethodInfo>();
static Example2()
{
_methods.Add(typeof(Foo), typeof(Foo).GetMethod("Calculate"));
_methods.Add(typeof(Bar), typeof(Bar).GetMethod("Compute"));
}
public static void Calc(object obj, int a)
{
_methods[obj.GetType()].Invoke(obj, new object[] { a });
}
}
// Using delegates
class Example3
{
private delegate void CalcDelegate(object obj, int a);
private static Dictionary<Type, CalcDelegate> _methods = new Dictionary<Type, CalcDelegate>();
static Example3()
{
_methods.Add(typeof(Foo), (o, a) => ((Foo)o).Calculate(a));
_methods.Add(typeof(Bar), (o, a) => ((Bar)o).Compute(a));
}
public static void Calc(object obj, int a)
{
_methods[obj.GetType()](obj, a);
}
}
// Using Reflection + overloaded methods
class Example4
{
private delegate void CalcDelegate(object obj, int a);
public static void Calc(object obj, int a)
{
Type[] types = new Type[] {
obj.GetType(), typeof(int)
};
typeof(Example4).GetMethod("Calc", types).Invoke(null, new object[] { obj, a });
}
public static void Calc(Foo obj, int a)
{
obj.Calculate(a);
}
public static void Calc(Bar obj, int a)
{
obj.Compute(a);
}
}
Thanks!
Use extension methods to essentially add a new function to an existing type.
http://msdn.microsoft.com/en-us/library/bb383977.aspx
This is how I would write the solution. It reduces the risk of type safety problems in the code and eliminates reflection.
class Example2
{
private static Dictionary<Type, Action<object,int>> _methods = new Dictionary<Type, Action<object,int>>();
static Example2()
{
Add<Foo>( (f,a) => f.Calculate(a) );
Add<Bar>( (b,a) => b.Compute(a) );
}
public static void Calc<TSource>(TSource source, int a)
{
_methods[typeof(TSource)](source,a);
}
public static void Add<TSource>(Action<TSource,int> del)
{
Action<object,int> wrapper = (x,i) => { del((TSource)x, i); };
_methods[typeof(TSource)] = wrapper;
}
}
you could always use the adapter pattern to implement the unchangeable legacy objects, without breaking any objects dependant on its functionality, while still being ableto implement your own (new) functionality to the object.
I would go for example 1, because its the simplest one and most obvious.
I would use Example 2 only if you expect new types of objects with one of these two methods, and example 3 only if you have a lot (tens if not hundreds) of objects and performance starts being an issue.
Edit: Or extension methods if you are .Net 3