How to add method with parameter in a list - c#

I have generic delegates.
public delegate void Metodo();
public delegate void Metodo<T>(T parametro);
public delegate void Metodo<T, U>(T parametro1, U parametro2);
public delegate void Metodo<T, U, V>(T parametro1, U parametro2, V parametro3);
public delegate void Metodo<T, U, V, W>(T parametro1, U parametro2, V parametro3, W parametro4);
And a list:
private List<Metodo> ListOfMethods;
I add methods without parameters like this:
public void Method();
ListOfMethods.Add(Method);
How i can add methods with parameters in my list ?
Like this is my whole class.
public class ListOfUpdateMethods
{
public delegate void Metodo();
public delegate void Metodo<T>(T parametro);
public delegate void Metodo<T, U>(T parametro1, U parametro2);
public delegate void Metodo<T, U, V>(T parametro1, U parametro2, V parametro3);
public delegate void Metodo<T, U, V, W>(T parametro1, U parametro2, V parametro3, W parametro4);
private List<Metodo> MetodosPreAtualizacao;
private List<Metodo> MetodosAtualizacao;
public ListOfUpdateMethods()
{
this.MetodosPreAtualizacao = new List<Metodo>();
this.MetodosAtualizacao = new List<Metodo>();
}
public void AddMetodosPreAtualizacao(Metodo m)
{
this.MetodosPreAtualizacao.Add(m);
}
public void AddMetodosAtualizacao(Metodo m)
{
this.MetodosAtualizacao.Add(m);
}
public void ExecutaMetodosPreAtualizacao()
{
foreach (var metodos in this.MetodosPreAtualizacao)
metodos();
}
public void ExecutaMetodosAtualizacao()
{
foreach (var metodos in this.MetodosAtualizacao)
metodos();
}
}
I use in Method into a Windows Form:
private void UpdadeControl(ListOfUpdateMethods list, Control control)
{
list.ExecutaMetodosPreAtualizacao();
if (control.InvokeRequired)
{
var action = new Action<ListOfUpdateMethods, Control>(UpdadeControl);
control.Invoke(action, new object[] { list, control });
}
else
{
list.ExecutaMetodosAtualizacao();
}
}
I'm looking for the best way to write a generic method to update the controls on my form.

You can create a list of MulticastDelegate. For example:
List<MulticastDelegate> multicastDelegates = new List<MulticastDelegate>();
multicastDelegates.Add(new Action(() => Console.WriteLine("Hello World!")));
multicastDelegates.Add(new Action<int>(x => Console.WriteLine(x)));
foreach (var multicastDelegate in multicastDelegates)
{
if (multicastDelegate is Action<int> actionInt)
{
actionInt(1);
}
else if (multicastDelegate is Action action)
{
action();
}
}

You could do it by creating a List<Action> and adding invocations of the various delegates.
A List<Action> could contain any sort of action, not just one of these delegates. If you encapsulate the list you can ensure that only the types of actions you want get added.
public class MetodoList
{
private readonly List<Action> _metodos = new List<Action>();
public void Add(Metodo metodo)
{
_metodos.Add(metodo.Invoke);
}
public void Add<T>(Metodo<T> metodo, T argument)
{
_metodos.Add(() => metodo.Invoke(argument));
}
public void Add<T, U>(Metodo<T, U> metodo, T thing, U uther)
{
_metodos.Add(() => metodo.Invoke(thing, uther));
}
// more of these.
public void InvokeAll()
{
_metodos.ForEach(m => m.Invoke());
}
}
While I don't know what this is for, here's how you would use it:
var metodos = new MetodoList();
var target = new HasMetodos();
metodos.Add(target.DoSomething);
metodos.Add(target.DoSomethingWithTwoArguments, "x", 1);
metodos.InvokeAll();

Related

C# - Trying construct a class from a function, getting Cannot convert method group error

I'm trying to encapsulate a function inside a class but it's not working. What am I missing here?
public class MyClass<Return, T>
{
public delegate void D01(T val);
public D01 d01;
public delegate void D02(T val, T val2);
public D02 d02;
public MyClass(D01 func)
{
d01= func;
}
public MyClass(D02 func)
{
d02= func;
}
}
public class ABC
{
public void MyGenericFunction<T>(MyClass<T, T> function, T var01)
{
...
}
}
class OtherClass
{
private ABC abc = new ABC();
private void Test(float x) {...}
private void OtherFunc()
{
float x = 1.0f;
abc.MyGenericFunction<float>(Test, x);
//Gives Cannot convert method group to MyClass<float,float> error
}
}
It should be able to convert function to the delegate of the same type. I also have the same constructor with Func and Action parameters but couldn't get them to work either.
Woah, heaps of stuff going on here.. I guess you actually want Func apposed to MyClass<T, T> function
public void MyGenericFunction<T>(Func<T, T> function, T var01)
{
...
}
...
private float Test(float x)
{
...
}
private void OtherFunc()
{
float x = 1.0f;
abc.MyGenericFunction<float>(Test, x);
}
On the off chance you actuall want
public void MyGenericFunction<T>(MyClass<T, T> function, T var01)
Then youd likely want something more like this
abc.MyGenericFunction<float>(new MyClass<float, float>(Test), x);

initialising a delegate with a string

Is there any way to initialise a delegate with a string? I.e. you won't know the name of the function that needs to be called at runtime? Or I'm guessing there is a better way of doing this?
delegate void TestDelegate(myClass obj);
void TestFunction()
{
TestDelegate td = new TestDelegate(myFuncName); // works
TestDelegate td = new TestDelegate("myFuncName"); // doesn't work
}
Update
Is is the code I currently have which is not working
class Program
{
static void Main(string[] args)
{
Bish b = new Bish();
b.MMM();
Console.Read();
}
}
class Bish
{
delegate void TestDelegate();
public void MMM()
{
TestDelegate tDel = (TestDelegate)this.GetType().GetMethod("PrintMe").CreateDelegate(typeof(TestDelegate));
tDel.Invoke();
}
void PrintMe()
{
Console.WriteLine("blah");
}
}
You can create a dynamic delegate this way
class Bish
{
delegate void TestDelegate();
delegate void TestDelegateWithParams(string parm);
public void MMM()
{
TestDelegate tDel = () => { this.GetType().GetMethod("PrintMe").Invoke(this, null); };
tDel.Invoke();
TestDelegateWithParams tDel2 = (param) => { this.GetType().GetMethod("PrintMeWithParams").Invoke(this, new object[] { param }); };
tDel2.Invoke("Test");
}
public void PrintMe()
{
Console.WriteLine("blah");
}
public void PrintMeWithParams(string param)
{
Console.WriteLine(param);
}
}

Passing a method as a parameter with parameters

So I know how to do:
void PrintFoo () { Console.Write("Foo");}
void DoSomething (Action methodToCall) { methodToCall();}
void Main () { DoSomething(PrintFoo); }
What I want to do:
void PrintFoo (string fooToPrint) { Console.Write(fooToPrint);}
void DoSomething (Action methodToCall) { methodToCall();}
void Main () { DoSomething(PrintFoo("Foo bar baz")); }
Basically call an action WITH Parameters
Use a lambda expression:
void PrintSomething(string stringToPrint) { Console.Write(stringToPrint); }
void DoSomething(Action methodToCall) { methodToCall(); }
void Main()
{
DoSomething(() => PrintSomething("Message"));
}
You may also define actions to require parameter types for the callback.
public void DoSomething(Action<string> Callback){
var result = getMyString();
Callback(result);
}
public void DoSomething(Action<string> CallBack, List<string> Parms){
var sb = new StringBuilder();
Parms.ForEach(p=> sb.Append(Parse(p));
Callback(sb.ToString());
}

How to use Action with unknown number of Parameters

Hi i would like to do something like:
public class Subscription
{
private Action _action; //????
public Subscription( Action a )//????
{
_action = a; //????
}
}
public class testklass
{
public testklass()
{
new Subscription(a); // just to show you how i want to submit
new Subscription(b);
new Subscription(c);
}
private void a() { }
private void b(string gg){}
private void c(int i, string g) { }
}
Is there a way to do this?
And will it cost much performance?
Any advice is greatly appreciated
EDIT:
i going to bild a Mediator
testklass is just a subscriber who create a Subscription Object and Hand it over to the Mediator
who does the logic behind all this when a other Class publish a Object/s that match the subscribtion
but at the moment only want to now how to store a Action with unknown number of Parameters in my Container Object Subscription
public class Subscription<T>
{
private T _action;
public Subscription(T a)
{
_action = a;
}
}
you can use it like;
Action<int> func1 = (q) => q += 1;
Action<int,int> func2 = (q,w) => q += w;
Subscription<Action<int>> s1 = new Subscription<Action<int>>(func1);
Subscription<Action<int,int>> s2 = new Subscription<Action<int,int>>(func2);
As a side note, I do not know what you are trying to do but there may be a better way of doing it.
public class testklass
{
public testklass()
{
new Subscription(a); // just to show you how i want to submit
new Subscription(() => b("someparam"));
new Subscription(()=>c(10, "someparam"));
}
private void a() { }
private void b(string gg) { }
private void c(int i, string g) { }
}
you could make your function get in determinant count of various params within the following syntax
resultType functionName(params object[] list) {...}
And then using that function with any count of parameters you want.
Also you could implement function parameters like an array or list or object. Then your function will take only one argument - the object which store your params.
So, as you can see there are a plenty of ways to do that.

How to convert an action to a defined delegate of the same signature?

class Test
{
public delegate void FruitDelegate(Fruit f);
public void Notify<T>(Action<T> del) where T : Fruit
{
FruitDelegate f = del; // Cannot implicitly convert type 'Action<T>' to 'FruitDelegate
}
}
Fruit is an empty class. Both of these delegates have the same signature.
I cannot seem to get any of this working. Maybe it would help if I explained what I am trying to do (provide some context).
I want to create a class that has a generic static method that provides a type and a method callback (like the above example).
The problem I am having is that the delegate contains a parameter and I don't want to have to cast it within the method callback. For example, I want this:
public void SomeMethod()
{
Test.Notify<Apple>(AppleHandler);
}
private void AppleHandler(Apple apple)
{
}
Instead of this:
public void SomeMethod()
{
Test.Notify<Apple>(AppleHandler);
}
private void AppleHandler(Fruit fruit)
{
Apple apple = (Apple)fruit;
}
Is this kind of thing possible?
is this what you want?
static void Main(string[] args)
{
Program p = new Program();
p.SomeMethod();
}
public class Fruit
{ }
public class Apple : Fruit { }
public delegate void FruitDelegate<in T>(T f) where T : Fruit;
class Test
{
public static void Notify<T>(FruitDelegate<T> del)
where T : Fruit, new()
{
T t = new T();
del.DynamicInvoke(t);
}
}
private void AppleHandler(Apple apple)
{
Console.WriteLine(apple.GetType().FullName);
}
public void SomeMethod()
{
FruitDelegate<Apple> del = new FruitDelegate<Apple>(AppleHandler);
Test.Notify<Apple>(del);
}
There is good reason you cannot do this. Suppose the rest of your method was:
class Test
{
public delegate void FruitDelegate(Fruit f);
public void Notify<T>(Action<T> del) where T : Fruit
{
FruitDelegate f = del;
f(new Banana()); //should be legal, but del may be Action<Apple>
}
}
That would definitely not work, so the compiler is correct here.
What about something like this?
public void Notify<T>(Action<T> del) where T : Fruit
{
FruitDelegate f = fruit => del((T)fruit);
}
The FruitDelegate instance, when invoked, would throw an InvalidCastException if, say, an AppleHandler was invoked with a Banana argument.

Categories

Resources