elyashiv
elyashiv

Reputation: 3691

finding a function in c# based on a attribute value

I want to access function of a class, through some adapter, based on a attribute value. all functions have the same prototype
the way I thought to do it is to declare a Dictionary like that:

Dictionary<key_values, Delegate_of_Functions>

where key_values a class that contains the values that identify a function, and Delegate_of_Functions is a delegate of the functions type.

now, I tried to do the following:

Functions = new Dictionary<string, function>();

var a = from Fun in typeof(TheFunctionsContainer).GetMethods()
        where Fun.GetCustomAttributes(typeof(The_Attribute), true).Length != 0
        select Fun;

foreach (var c in a)
{
  Functions.Add(
    c.GetCustomAttributes(true).OfType<The_Attribute>().First().key,
    new function(c)); // this line dose not compile
}

my questions are:

Upvotes: 2

Views: 207

Answers (2)

sloth
sloth

Reputation: 101072

Given that function is a delegate

delegate void function();

you can use the Delegate.CreateDelegate method for creating a delegate

var Functions = new Dictionary<string, function>();

var a = typeof(TheFunctionsContainer).GetMethods().Where(f => f.GetCustomAttributes(typeof(The_Attribute), true).Any());

foreach (var c in a)
{
    Functions.Add(
      c.GetCustomAttributes(true).OfType<The_Attribute>().First().key,
      (function)Delegate.CreateDelegate(typeof(function), c)); 
}

If you want to execute non-static methods on an instance, you have to provide the instance you want the methods call on to Delegate.CreateDelegate:

(function)Delegate.CreateDelegate(typeof(function), yourInstance, c)

or just see svicks comment :-)

Upvotes: 2

O. R. Mapper
O. R. Mapper

Reputation: 20731

A straightforward way to do this is to invoke the Invoke method on the methods you have found. You can do that in anonymous delegates added to your dictionary.

You say all of your functions have the same prototype (that's usually called a signature in C#), but as you don't indicate what signature that is, I'll simply assume a void method that takes a string and an integer (represented by an Action<string, int> in my sample code below). I trust you can change the code so it suits you :-)

Each element in a, that is, each c in your foreach loop, is of type MethodInfo:

var Function = new Dictionary<string, Action<string, int>>();

// your code for discovering the suitable functions and filling a

foreach (var c in a) {
    Functions.Add(c.GetCustomAttributes(true).OfType<The_Attribute>().First().key,
      (s, i) => {
          c.Invoke(null, new object[] { s, i });
      });
}

Before adding anything to that dictionary, you may want to check whether the MethodInfo instance indicates that the method really has the desired signature, though. Otherwise, someone might intentionally or unintentionally mark a method with a different signature with that attribute and the call to Invoke will fail.

Upvotes: -1

Related Questions