bflemi3
bflemi3

Reputation: 6790

Delegate Methods - how to call and pass arguments if I don't know what type or how many arguments

Let's say I have a delegate...

public delegate void MyAction(params object[] args);

And a class with a subclass that uses that delagate...

public class MyClass {
    public List<MySubClass> mySubClasses;
}

public class MySubClass {
    public string myString;
    public MyAction myDelegateMethod;
}

I want to be able to pass any method to myDelegateMethod, which could accept any number of arguments with varying types, at runtime. Something like this...

MyClass myClass = new MyClass(){
    mySubClasses = {
        new MySubClass {
            myString = "help",
            myDelegateMethod = Method1 
        },
        new MySubClass {
            myString = "me",
            myDelegateMethod = Method2 
        }
    }   
};

public string Method1(object myObject) { ... }
public string Method2(string value, Guid id) { ... }

How would I call each of these methods at runtime passing the appropriate arguments in?

myClass.mySubClasses.ForEach(x => {
    x.myDelegateMethod; // <-- this is where I'm stumped. how do i pass arguments here?
});

Is this possible? Perhaps I have something implemented wrong?

Upvotes: 2

Views: 380

Answers (2)

igofed
igofed

Reputation: 1442

First of all Method2 can't be used as your delegate. Also it's not a good practice to do so. You can try to do it with reflection, but it will be hardly understandable for others, who will read your code. So, I think, you should use all methods like you delegate type but cast to need types inside methods, like this:

public void Method1(params object[] pars)
{
    string value = (string)pars[0];
    Guid id = (Guid)pars[1];
}

or use some sort of closures from previous answer.

Upvotes: 0

Tejs
Tejs

Reputation: 41236

This isn't possible, because Method1 and Method2 are NOT void <Name> (params object) delegates. They aren't the same type (or even convertible with variance to a compatible type), considering they return different values and take different parameters to execute.

If you wanted to execute an arbitrary method, then the only way I can think of would be to take a wrapped method execution as an action:

var sample = new List<MyClass>
{
    new MyClass
    {
        SomeProperty = "Help",
        Method = new Action(() =>
          {
              ExecuteMethod1("Hello", "World");
          })
    },
    new MyClass
    {
        SomeProperty = "Me",
        Method = new Action(() =>
          {
              ExecuteMethod2(1, 2, 3, 4);
          })
    },
};

And then you could execute like so:

myClass.ForEach(x => x.Method());

In this situation you need to explicitly wrap whatever you want to do (with parameters known at create time) the method you want to stick in Method.

Upvotes: 2

Related Questions