Reputation: 7852
I have a collection of delegates:
IList<Action<ISomeInterface>> _delegates = new List<Action<ISomeInterface>>();
And a method* to add delegates to it**:
public void AddDelegate<T>(Action<T> del) where T : ISomeInterface
{
_delegates.Add(si => del((T)si));
}
Now I want to filter the delegates collection based on the concrete type the delegate is constructed with:
var aDelegates = _delegates.Where(d => d is Action<SomeInterfaceImplA>);
foreach(var del in aDelegates)
{
....
}
Which will return all delegates, not only Action<SomeInterfaceImplA>
delegates. So my question is, what predicate should be used in the Where
clause to get the correct subset from the filtering? Full code example is available here.
* A fluent API (generic) method is using it hence the use of a generic type here
** Based on the answer here
Upvotes: 0
Views: 585
Reputation: 13224
I am not sure that the construction you have currently makes any sense. You may want to change what you are doing if you want to filter your delegates by concrete expected implementation argument type, by changing this:
IList<Action<ISomeInterface>> _delegates = new List<Action<ISomeInterface>>();
to this:
IDictionary<Type, List<Action<ISomeInterface>>> _delegates =
new Dictionary<Type, List<Action<ISomeInterface>>>();
And the AddDelegate
method to
public void AddDelegate<T>(Action<T> del) where T : ISomeInterface
{
var list = default(List<Action<ISomeInterface>>);
if (!_delegates.TryGetValue(typeof(T), out list))
_delegates[typeof(T)] = list = new List<Action<ISomeInterface>>();
list.Add(si => del((T)si));
}
And use the dictionary to filter by argument type.
The reason why your current code will not work, is that all of the registered actions are actually of type Action<ISomeInterface>
, that their method body (si => del((T)si
) performs a dangerous cast of its argument to a type T
does not change that.
Upvotes: 1
Reputation: 987
This not be the prettiest thing ever, but it works
var aDelegates = someClass.Delegates.Where(d =>
d.Method.DeclaringType.GenericTypeArguments.FirstOrDefault().IsAssignableFrom(typeof(SomeInterfaceImplA)));
Upvotes: 1