Reputation: 3691
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
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
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