c# different delegate add in dictionary and run deleagate method from dictionary - c#

With C#
I want to my delegate method into one dictionary, and put them all out and run.
for example
class class1{
Func<string,int> method1 = new Func<string,int>( x => 3);
Func<int,double> method2 = new Func<string,int>( x => 3.0);
Func<double,bool> method3 = new Func<string,int>( x => true);
Dictionary<string, dynamic> dic = new Dictionary<string, dynamic>();
dic.add("m1",method1)
dic.add("m2",method2)
dic.add("m3",method3)
// rund all method
dynamic RunMethod(Dictionary<string, dynamic> dic , dynamic firstInput, int index = 0)
{
if(index = dic.count) return
RunMethod(dic, dic.ElementAt[index].value(input) , index + 1)
}
void main ()
{
RunMethod( dix , "firstString" )
}
}
(this code has error but expression of what i want to do )
What i want to do is like below.
Create Method 1, 2 ,3
Output type of Method 1 = Input type of Method2 ,
Output type of Method 2 = Input type of Method3
Finally get output of Method3
There is Run Method that take Input that has type of method1 and method dictionary (or list or something)
I want to additional method that check what type of method 1? and output type of method 3

Not sure what are you exactly looking for. This code sample may help you.
class Class1
{
public Func<string, int> method1 = new Func<string, int>(x => 3);
public Func<int, double> method2 = new Func<int, double>(x => 4.0);
public Func<double, bool> method3 = new Func<double, bool>(x => true);
List<Delegate> methodList = new List<Delegate>();
public Class1()
{
methodList.Add(method1);
methodList.Add(method2);
methodList.Add(method3);
}
public object RunMethods(object param)
{
foreach(Delegate del in methodList)
{
param = del.DynamicInvoke(param);
}
return param;
}
}
static void Main(string[] args)
{
Class1 obj = new Class1();
object result = obj.RunMethods("some string");
}

Related

Arithmetic operation like Add for a Generic List<T>

Doing Add for two elements like T a, T b is simple, Mark has provided a good solution using Expression tree here, which translates into following and is simple to use:
static T Add<T>(T a, T b)
{
// Declare Parameter Expressions
ParameterExpression paramA = Expression.Parameter(typeof(T), "valueA"),
paramB = Expression.Parameter(typeof(T), "valueB");
// add the parameters together
BinaryExpression body = Expression.Add(paramA, paramB);
// Compile it
Func<T, T, T> add = Expression.Lambda<Func<T, T, T>>(body, paramA, paramB).Compile();
// Call it
return add(a, b);
}
Challenge that I have is there's a collection of List<T>, where all elements have to added as shown above. I have tried following, on same lines as above, but it doesn't work:
static T AddAll<T>(List<T> list)
{
var parameterExpressionList = list.Select((x,i) => (Expression)Expression.Parameter(typeof(T), "value"+i));
var body = parameterExpressionList
.Skip(1)
.Aggregate(parameterExpressionList.First(),
(paramA, paramB) => Expression.Add(paramA, paramB));
// Compile it
Func<List<T>, T> addAll = Expression.Lambda<Func<List<T>, T>>(body, parameterExpressionList.Cast<ParameterExpression>()).Compile();
return addAll(list);
}
Run-time error that I get is: Incorrect number of parameters supplied for lambda declaration. Any pointer, how to achieve, please note, I don't need a solution where I cumulatively pick two elements from actual list and call Add<T>(T a, T b) , since that would lead to multiple times compilation of the Expression tree, which is not efficient, as I would have > 100 K data points, any suggestion to make my code work would be great, I am not sure where it is going wrong.
Since you have created a generic function, just use it on the list (I added an optional Adder method to handle non-standard classes):
static T AddAll<T>(IEnumerable<T> src, Func<T, T, T> adder = null) {
// Declare Parameter Expressions
ParameterExpression paramA = Expression.Parameter(typeof(T), "valueA"),
paramB = Expression.Parameter(typeof(T), "valueB");
// add the parameters together
BinaryExpression body;
if (adder == null)
body = Expression.Add(paramA, paramB);
else
body = Expression.Add(paramA, paramB, adder.GetMethodInfo());
// Compile it
Func<T, T, T> add = Expression.Lambda<Func<T, T, T>>(body, paramA, paramB).Compile();
// Call it
return src.Aggregate(default(T), (ans, n) => add(ans, n));
}
You can use the Adder parameter to handle things like strings:
var ans = AddAll(new[] { "a", "b", "c" }, String.Concat);
Since we know the type of T at compile time though, we can just call Sum:
static T AddAll2<T>(IEnumerable<T> src) {
var paramA = Expression.Parameter(typeof(IEnumerable<T>), "valueA");
var method = typeof(Enumerable).GetMethod("Sum", new[] { typeof(IEnumerable<T>) });
if (method != null) {
// Create lambda body
var body = Expression.Call(method, paramA);
// Compile it
Func<IEnumerable<T>, T> sum = Expression.Lambda<Func<IEnumerable<T>, T>>(body, paramA).Compile();
// Call it
return sum(src);
}
else
return default(T);
}
Of course, if you are going to call Sum, you don't need a lambda:
static T AddAll3<T>(IEnumerable<T> src) {
var method = typeof(Enumerable).GetMethod("Sum", new[] { typeof(IEnumerable<T>) });
if (method != null) {
// Call it
return (T)method.Invoke(null, new[] { src });
}
else
return default(T);
}
Just try to get every item from your list and then accumulate they into result.
static T AddAll<T>(List<T> list)
{
if (list.Count == 0)
{
// It's additional small case
return default(T);
}
var listParam = Expression.Parameter(typeof(List<T>));
var propInfo = typeof(List<T>).GetProperty("Item");
var indexes = list.Select((x, i) => Expression.MakeIndex(listParam, propInfo, new[] { Expression.Constant(i) }));
Expression sum = indexes.First();
foreach (var item in indexes.Skip(1))
{
sum = Expression.Add(sum, item);
}
var lambda = Expression.Lambda<Func<List<T>, T>>(sum, listParam).Compile();
return lambda(list);
}
You can pass list directly as argument and just create sum via indexes:
static T AddAll<T>(List<T> list)
{
if (list.Count == 0) return default(T);
if (list.Count == 1) return list[0];
var indexerProperty = typeof(List<T>).GetProperty("Item");
var p = Expression.Parameter(typeof(List<T>));
var exp = Expression.Add(
Expression.MakeIndex(p, indexerProperty, new [] { Expression.Constant(0) }),
Expression.MakeIndex(p, indexerProperty, new [] { Expression.Constant(1) }));
for (var i = 2; i < list.Count; i++)
{
exp = Expression.Add(
exp,
Expression.MakeIndex(p, indexerProperty, new [] { Expression.Constant(i) }));
}
var lambda = Expression.Lambda<Func<List<T>, T>>(exp, p).Compile();
return lambda(list);
}
Store all applicable Enumerable.Sum overloads in a dictionary:
// all methods with signature public static T Enumerable.Sum(IEnumerable<T>) by element type
private static readonly Dictionary<Type, MethodInfo> _sumMethodsByElementType = typeof(Enumerable)
.GetMethods(BindingFlags.Public | BindingFlags.Static)
.Where(m => m.Name == "Sum" && !m.IsGenericMethod)
.Select(m => new { Method = m, Parameters = m.GetParameters() })
.Where(mp => mp.Parameters.Length == 1)
.Select(mp => new { mp.Method, mp.Parameters[0].ParameterType })
.Where(mp => mp.ParameterType.IsGenericType && mp.ParameterType.GetGenericTypeDefinition() == typeof(IEnumerable<>))
.Select(mp => new { mp.Method, ElementType = mp.ParameterType.GetGenericArguments()[0] })
.Where(me => me.Method.ReturnType == me.ElementType)
.ToDictionary(mp => mp.ElementType, mp => mp.Method);
Invoke the corresponding one from inside the generic AddAll (or Sum as I prefer to call it) method:
public static T Sum<T>(IEnumerable<T> summands)
{
MethodInfo sumMethod;
if (!_sumMethodsByElementType.TryGetValue(typeof(T), out sumMethod)) throw new InvalidOperationException($"Cannot sum elements of type {typeof(T)}.");
return (T)sumMethod.Invoke(null, new object[] { summands });
}
Test:
Console.WriteLine(Sum(new[] { 1, 2, 3 }));
Console.WriteLine(Sum(new[] { 1, 2, 3, default(int?) }));
Console.WriteLine(Sum(new[] { 1.1, 2.2, 3.3 }));
Console.WriteLine(Sum(new[] { 1.1, 2.2, 3.3, default(double?) }));
try { Console.WriteLine(Sum(new[] { 'a', 'b', 'c' })); }
catch (InvalidOperationException ex) { Console.WriteLine(ex.Message); }
Output:
6
6
6.6
6.6
Cannot sum elements of type System.Char.
You don't necessarily need to solve every part of the problem with expressions, if you are just interested in the operation itself
Here's an implementation that uses Singleton via the Lazy<> type for the default addition of type T (instead of static methods)
The LinqExpression expression could potentially be reused if you really need expressions (say, in an EF scenario), but there's no equivalent expression for the AddAll operation... though it can potentially be expanded to support a generic expression for AddAll
public abstract class Addition<T>
{
private readonly Lazy<Expression<Func<T, T, T>>> _lazyExpression;
private readonly Lazy<Func<T, T, T>> _lazyFunc;
public Func<T, T, T> Execute
{
get { return _lazyFunc.Value; }
}
public Expression<Func<T, T, T>> LinqExpression
{
get { return _lazyExpression.Value; }
}
protected Addition()
{
_lazyExpression = new Lazy<Expression<Func<T, T, T>>>(InitializeExpression);
_lazyFunc = new Lazy<Func<T, T, T>>(() => LinqExpression.Compile());
}
protected abstract Expression<Func<T, T, T>> InitializeExpression();
}
public sealed class DefaultAddition<T> : Addition<T>
{
private static readonly Lazy<DefaultAddition<T>> _lazyInstance = new Lazy<DefaultAddition<T>>(() => new DefaultAddition<T>());
public static DefaultAddition<T> Instance
{
get {return _lazyInstance.Value; }
}
// Private constructor, you only get an instance via the Instance static property
private DefaultAddition()
{
}
protected override Expression<Func<T, T, T>> InitializeExpression()
{
var paramX = Expression.Parameter(typeof(T), "x");
var paramY = Expression.Parameter(typeof(T), "y");
var body = Expression.Add(paramX, paramY);
return Expression.Lambda<Func<T, T, T>>(body, paramX, paramY);
}
}
public static class Operations
{
public static T Add<T>(T x, T y)
{
return DefaultAddition<T>.Instance.Execute(x, y);
}
public static T AddAll<T>(IEnumerable<T> enumerable)
{
var itemAdd = DefaultAddition<T>.Instance.Execute;
return enumerable.Aggregate(default(T), (result, item) => itemAdd(result, item));
// This might be more efficient than Aggregate, but I didn't benchmark it
/*
var result = default(T);
foreach (var item in enumerable)
{
result = itemAdd(result, item);
}
return result;
*/
}
}
Usage:
// Can mix double with int :)
var doubleAdd = Operations.Add(4.5, 3);
// Can mix decimal with int :)
var listAdd = Operations.AddAll(new[] {3, 6.7m, 0.3m});
// Even empty enumerables
var shortAdd = Operations.AddAll(Enumerable.Empty<short>());
// This will not work for byte. System.Byte should be casted to System.Int32
// Throws "InvalidOperationException: The binary operator Add is not defined for the types 'System.Byte' and 'System.Byte'."
var byteAdd = Operations.AddAll(new byte[] {1, 2, 3});
If your T is of value type like int, long, double etc. then you can simply do this:
//add
//using System.Linq;
var items = new List<int>();
items.Add(1);
items.Add(5);
items.Add(10);
var sum = items.Sum();

Saving methods in a dictionary and use those methods on key match.

Public void test(){
Console.WriteLine("Hello World");
}
Is it possible to save this method in a Dictionary, and call this method if Dicitionary contains the method's key value.
For example like this:
Hashtable table = new Hashtable<method, string>();
string input = "hello"
foreach(Dictionary.entry t in table){
if(input == t.Key){
//Call the t.value method.
}
}
class Program
{
private static void Main(string[] args)
{
var methods = new Dictionary<string, Action>();
//choose your poison:
methods["M1"] = MethodOne; //method reference
methods["M2"] = () => Console.WriteLine("Two"); //lambda expression
methods["M3"] = delegate { Console.WriteLine("Three"); }; //anonymous method
//call `em
foreach (var method in methods)
{
method.Value();
}
//or like tis
methods["M1"]();
}
static void MethodOne()
{
Console.WriteLine("One");
}
}
Yes, that's pretty easy: just use the Action delegate class:
Encapsulates a method that has no parameters and does not return a value.
var dict = new Dictionary<string, Action>();
dict.Add("hello", test);
var input = "hello";
dict[input]();
Demo
You can use Func to reference your methods and then call them in the loop
https://msdn.microsoft.com/en-us/library/bb549151%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396
And as #Lucas Trzesniewski answered your can use Action if your methods has no params

wrap anonymous function with another call

I have this code in which I am trying to wrap an anonymous function by another call so when it is actually the wrapper's value that is returned and not the original function's.
In the code below however I get a NullPointerException in the last call. I am sure I am not doing something right, but beats me what it is.
class Program
{
public class MyClass
{
public int MyProp { get; set; }
}
private static List<Func<MyClass, object>> Calls;
private static object ExtraCall(int obj)
{
var returnVal = 8;
//do some stuff
return returnVal;
}
static void Main(string[] args)
{
Calls = new List<Func<MyClass, object>>();
Calls.Add(c => c.MyProp);
Func<MyClass, object> func = c => c.MyProp;
Calls.Add(c => ExtraCall((int)func(func.Target as MyClass)));
var obj = new MyClass(){ MyProp = 7 };
var test1 = Calls[0](obj);
var test2 = Calls[1](obj);
}
}
func.Target is null because this delegate doesn't have any instance which it is invoked on. You can try following code:
Calls.Add(c => ExtraCall((int)func(c)));

Cast delegate to Func in C#

I have code:
public delegate int SomeDelegate(int p);
public static int Inc(int p) {
return p + 1;
}
I can cast Inc to SomeDelegate or Func<int, int>:
SomeDelegate a = Inc;
Func<int, int> b = Inc;
but I can't cast Inc to SomeDelegate and after that cast to Func<int, int> with usual way like this:
Func<int, int> c = (Func<int, int>)a; // Сompilation error
How I can do it?
There's a much simpler way to do it, which all the other answers have missed:
Func<int, int> c = a.Invoke;
See this blog post for more info.
SomeDelegate a = Inc;
Func<int, int> b = Inc;
is short for
SomeDelegate a = new SomeDelegate(Inc); // no cast here
Func<int, int> b = new Func<int, int>(Inc);
You can't cast an instance of SomeDelegate to a Func<int, int> for the same reason you can't cast a string to a Dictionary<int, int> -- they're different types.
This works:
Func<int, int> c = x => a(x);
which is syntactic sugar for
class MyLambda
{
SomeDelegate a;
public MyLambda(SomeDelegate a) { this.a = a; }
public int Invoke(int x) { return this.a(x); }
}
Func<int, int> c = new Func<int, int>(new MyLambda(a).Invoke);
Try this:
Func<int, int> c = (Func<int, int>)Delegate.CreateDelegate(typeof(Func<int, int>),
b.Target,
b.Method);
The problem is that:
SomeDelegate a = Inc;
Isn't actually a cast. It's the short-form of:
SomeDelegate a = new SomeDelegate(Inc);
Therefore there's no cast. A simple solution to your problem can be this (in C# 3.0)
Func<int,int> f = i=>a(i);
This works (in C# 4.0 at least - not tried in earlier versions):
SomeDelegate a = Inc;
Func<int, int> c = new Func<int, int>(a);
If you look at the IL, this compiles into exactly the same code as Winston's answer. Here's the IL for the second line of what I just wrote:
ldloc.0
ldftn instance int32 ConsoleApplication1.Program/SomeDelegate::Invoke(int32)
newobj instance void class [mscorlib]System.Func`2<int32,int32>::.ctor(object, native int)
And that's also precisely what you see if you assign a.Invoke into c.
Incidentally, although Diego's solution is more efficient, in that the resulting delegate refers directly to the underlying method rather than going through the other delegate, it doesn't handle multicast delegates correctly. Winston's solution does, because it just defers completely to the other delegate. If you want a direct solution that also handles delegates with multiple targets, you need something a little more complex:
public static TResult DuplicateDelegateAs<TResult>(MulticastDelegate source)
{
Delegate result = null;
foreach (Delegate sourceItem in source.GetInvocationList())
{
var copy = Delegate.CreateDelegate(
typeof(TResult), sourceItem.Target, sourceItem.Method);
result = Delegate.Combine(result, copy);
}
return (TResult) (object) result;
}
This does the right thing for delegates with a single target by the way—it will end up producing just a single delegate of the target type that refers directly to whatever method (and where applicable, object) the input delegate referred to.
You can hack a cast by using a trick where you use the c# equivalent of a c++ union. The tricky part is the struct with two members that have a [FieldOffset(0)]:
[TestFixture]
public class Demo
{
public void print(int i)
{
Console.WriteLine("Int: "+i);
}
private delegate void mydelegate(int i);
[StructLayout(LayoutKind.Explicit)]
struct funky
{
[FieldOffset(0)]
public mydelegate a;
[FieldOffset(0)]
public System.Action<int> b;
}
[Test]
public void delegatetest()
{
System.Action<int> f = print;
funky myfunky;
myfunky.a = null;
myfunky.b = f;
mydelegate a = myfunky.a;
a(5);
}
}
It is the same kind of problem as this:
public delegate int SomeDelegate1(int p);
public delegate int SomeDelegate2(int p);
...
SomeDelegate1 a = new SomeDelegate1(Inc);
SomeDelegate2 b = (SomeDelegate2)a; // CS0030
which is the same kind of problem as:
public class A { int prop { get; set; } }
public class B { int prop { get; set; } }
...
A obja = new A();
B objb = (B)obja; // CS0029
Objects cannot be casted from one type to an unrelated other type, even though the types are otherwise completely compatible. For lack of a better term: an object has type identity that it carries along at runtime. That identity cannot be changed after the object is created. The visible manifestation of this identity is Object.GetType().
I like examples. Here is my example code:
class Program
{
class A
{
public A(D d) { d.Invoke("I'm A!"); }
public delegate string D(string s);
}
class B
{
public delegate string D(string s);
}
static void Main(string[] args)
{
//1. Func to delegates
string F(dynamic s) { Console.WriteLine(s); return s; }
Func<string, string> f = F;
//new A(f);//Error CS1503 Argument 1: cannot convert from 'System.Func<string, string>' to 'ConsoleApp3.Program.A.D'
new A(new A.D(f));//I'm A!
new A(x=>f(x));//I'm A!
Func<string, string> f2 = s => { Console.WriteLine(s); return s; };
//new A(f2);//Same as A(f)
new A(new A.D(f2));//I'm A!
new A(x => f2(x));//I'm A!
//You can even convert between delegate types
new A(new A.D(new B.D(f)));//I'm A!
//2. delegate to F
A.D d = s => { Console.WriteLine(s); return s; };
Func<string, string> f3 = d.Invoke;
f3("I'm f3!");//I'm f3!
Func<string, string> f4 = new Func<string, string>(d);
f4("I'm f4!");//I'm f4!
Console.ReadLine();
}
}
The output is:

Is there a delegate available for properties in C#?

Given the following class:
class TestClass {
public void SetValue(int value) { Value = value; }
public int Value { get; set; }
}
I can do
TestClass tc = new TestClass();
Action<int> setAction = tc.SetValue;
setAction.Invoke(12);
which is all good. Is it possible to do the same thing using the property instead of the method? Preferably with something built in to .net.
You could create the delegate using reflection :
Action<int> valueSetter = (Action<int>)Delegate.CreateDelegate(typeof(Action<int>), tc, tc.GetType().GetProperty("Value").GetSetMethod());
or create a delegate to an anonymous method which sets the property;
Action<int> valueSetter = v => tc.Value = v;
Edit: used wrong overload for CreateDelegate(), need to use the one that takes and object as target. Fixed.
There are three ways of doing this; the first is to use GetGetMethod()/GetSetMethod() and create a delegate with Delegate.CreateDelegate. The second is a lambda (not much use for reflection!) [i.e. x=>x.Foo]. The third is via Expression (.NET 3.5).
The lambda is the easiest ;-p
class TestClass
{
public int Value { get; set; }
}
static void Main()
{
Func<TestClass, int> lambdaGet = x => x.Value;
Action<TestClass, int> lambdaSet = (x, val) => x.Value = val;
var prop = typeof(TestClass).GetProperty("Value");
Func<TestClass, int> reflGet = (Func<TestClass, int>) Delegate.CreateDelegate(
typeof(Func<TestClass, int>), prop.GetGetMethod());
Action<TestClass, int> reflSet = (Action<TestClass, int>)Delegate.CreateDelegate(
typeof(Action<TestClass, int>), prop.GetSetMethod());
}
To show usage:
TestClass foo = new TestClass();
foo.Value = 1;
Console.WriteLine("Via property: " + foo.Value);
lambdaSet(foo, 2);
Console.WriteLine("Via lambda: " + lambdaGet(foo));
reflSet(foo, 3);
Console.WriteLine("Via CreateDelegate: " + reflGet(foo));
Note that if you want the delegate pointing to the specific instance, you can use closures for the lambda, or the overload of CreateDelegate that accepts and instance.
Properties are really wrappers around methods in .Net, so using reflection you should be able to get the delegate (set_PROPERTY and get_PROPERTY) and then execute them...
See System.Reflection.PropertyInfo
If has two methods which you can use to get/ set the value - GetGetMethod and GetSetMethod.
So you could write:
var propertyInfo = typeof (TestClass).GetProperty ("Value");
var setMethod = property.GetSetMethod (); // This will return a MethodInfo class.

Categories