Lostblue Lostblue -4 years ago 66
C# Question

Advanced DynamicInvocation of arguments for a "Delegated Switch"

Context

In my free time, I wanted to develop a tools that will fulfill the following needs :


  • Looping over a bit[] value to execute a determined method for each True.

  • Easy to implement a new method and easy to call overall in case of new filter OR adding length to the bit[] values.



I called this need "Delegated Switch" but their is no real relation to
switch
...




Needs

I realized that I also want to give arguments to my methods (which could be different from a method to another). So I searched for solutions and found tricks to not have arguments using inheritance of
OperatorOnFilter
.

What I want to know is:


  • Does it exist a way to do that without inheritance (changing
    OperatorOnFilter
    )?

  • (Optionally if not, any architectural recommendation?)

  • (Optionally, Delegate.DynamicInvoke() is a bit slow. Any better idea?)






Existing Code

public class OperatorOnFilter
{
Dictionary<int, Delegate> Operations;
public OperatorOnFilter() { Operations = new Dictionary<int, Delegate>(); }

public void AddOrReplace(int numTraitement, Delegate Action)
{
if (Operations.ContainsKey(numTraitement))
Operations[numTraitement] = Action;
else
Operations.Add(numTraitement, Action);
}

public void ApplyOperations(FilterManager Filter)
{
for (int i = 0; i < Filter.Values.Count(); i++)
if (Operations.ContainsKey(i) && Filter.Values[i])
Operations[i].DynamicInvoke();
}
}

public class FilterManager
{
public bool[] Values;
public FilterManager(int filtre)
{
List<bool> tmpList = new List<bool>();
int i = 0;
while (filtre >> i > 0)
{
tmpList.Add((filtre & (1 << i)) == (1 << i));
i++;
}
Values = tmpList.ToArray();
}
}


Test

class Program
{
static int theYes = 0;

delegate void operate();
static void Main(string[] args)
{
int i = 0;
OperatorOnFilter myOperators = new OperatorOnFilter();
myOperators.AddOrReplace(0, (operate)delegate() { Console.Write("a"); theYes++; }); //1
myOperators.AddOrReplace(1, (operate)delegate() { Console.Write("b"); theYes++; }); //2
myOperators.AddOrReplace(2, (operate)delegate() { Console.Write("c"); theYes++; }); //4

myOperators.ApplyOperations(new FilterManager(7)); //"abc" 7 = 1 + 2 + 4
myOperators.ApplyOperations(new FilterManager(3)); //"ab" 3 = 1 + 2
myOperators.ApplyOperations(new FilterManager(6)); //"bc" 6 = 2 + 4

Console.WriteLine(theYes); // 7

Console.ReadKey();
}

}
// FINAL RESULT :
// abcabbc
// 7

Answer Source

Based on @Erk comments and some self improvement. I found my answers using explicit parameters on delegate and on my AddOrReplace methods.

Final Code (Tuple is added since I work with .NET 3.5)

public class OperatorOnFilter
{
    Dictionary<int, Tuple<int, object[]>> Operations = new Dictionary<int, Tuple<int, object[]>>();
    List<Delegate> lstOperations = new List<Delegate>();

    public OperatorOnFilter() { }

    public void AddOrReplace(int numTraitement, Delegate Action, params object[] Arguments)
    {
        if (!lstOperations.Contains(Action))
            lstOperations.Add(Action);

        if (Operations.ContainsKey(numTraitement))
            Operations[numTraitement] = new Tuple<int, object[]>(lstOperations.IndexOf(Action), Arguments);
        else
            Operations.Add(numTraitement, new Tuple<int, object[]>(lstOperations.IndexOf(Action), Arguments));
    }

    public void ApplyOperations(FilterManager Filter)
    {
        for (int i = 0; i < Filter.Values.Count(); i++)
            if (Operations.ContainsKey(i) && Filter.Values[i])
                lstOperations[Operations[i].First].DynamicInvoke(Operations[i].Second);
    }

}

public class FilterManager
{
    public bool[] Values;
    public FilterManager(int filtre)
    {
        List<bool> tmpList = new List<bool>();
        int i = 0;
        while (filtre >> i > 0)
        {
            tmpList.Add((filtre & (1 << i)) == (1 << i));
            i++;
        }
        Values = tmpList.ToArray();
    }
}

public class Tuple<T1, T2>
{
    public T1 First { get; private set; }
    public T2 Second { get; private set; }
    internal Tuple(T1 first, T2 second)
    {
        First = first;
        Second = second;
    }
}

public static class Tuple
{
    public static Tuple<T1, T2> New<T1, T2>(T1 first, T2 second)
    {
        var tuple = new Tuple<T1, T2>(first, second);
        return tuple;
    }
}

Test Class

class Program
{
    static int theYes = 0;

    delegate void operate1();
    delegate void operate2(string a);
    delegate void operate3(string a, uint x);
    static void Main(string[] args)
    {
        int i = 0;
        OperatorOnFilter myOperators = new OperatorOnFilter();
        myOperators.AddOrReplace(0, (operate1)delegate() { Console.Write("a"); theYes++; }); //1
        myOperators.AddOrReplace(1, (operate2)delegate(string a) { Console.Write(a); theYes++; }, "b"); //2
        myOperators.AddOrReplace(2, (operate3)delegate(string a, uint x) { for (uint j = 0U; j < x; j++) { Console.Write(a); theYes++; } }, "c", 3U); //4

        myOperators.ApplyOperations(new FilterManager(7));      //"abccc" 7 = 1 + 2 + 4
        myOperators.ApplyOperations(new FilterManager(3));     //"ab" 3 = 1 + 2
        myOperators.ApplyOperations(new FilterManager(6));    //"bccc" 6 = 2 + 4

        Console.WriteLine(theYes); // 11

        Console.ReadKey();
    }

}
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download