开发者

How do I put all types implementing a certain generic interface in a dictionary?

Given a particular interface ITarget<T> and a particular type myType, here's how you would determine T if myType implements ITarget<T>. (This code snippet is taken from the answer to an earlier question.)

foreach (var i in myType.GetInterfaces ())
    if (i.IsGenericType
        && i.GetGenericTypeDefinition() == typeof(ITarget<>))
        return i.GetGenericArguments ()[0] ;

However, this only checks a single type, myType. How would I create a dictionary of all such type parameters, where the key is T开发者_Python百科 and the value is myType? I think it would look something like this:

var searchTarget = typeof(ITarget<>);
var dict = Assembly.GetExecutingAssembly().[???]
             .Where(t => t.IsGenericType
                    && t.GetGenericTypeDefinition() == searchTarget)
             .[???];

What goes in the blanks?


var searchTarget = typeof(ITarget<>);

var dict = Assembly.GetExecutingAssembly()
    .GetTypes()
    .SelectMany(t => t.GetInterfaces()
                      .Where(i => i.IsGenericType
                          && (i.GetGenericTypeDefinition() == searchTarget)
                          && !i.ContainsGenericParameters),
                (t, i) => new { Key = i.GetGenericArguments()[0], Value = t })
    .ToDictionary(x => x.Key, x => x.Value);

Note that if you have multiple classes implementing ITarget<> and using the same generic type argument -- for example, class Foo : ITarget<string> and class Bar : ITarget<string> -- then the ToDictionary call will fail with an ArgumentException complaining that you can't add the same key twice.

If you do need a one-to-many mapping then you have a couple of options available.

  1. Use ToLookup rather than ToDictionary to generate a Lookup<K,V>:

    var dict = Assembly.GetExecutingAssembly()
        .GetTypes()
        .SelectMany(/* ... */)
        .ToLookup(x => x.Key, x => x.Value);
    
  2. If you prefer to work with something like a Dictionary<K,List<V>> then you could do this:

    var dict = Assembly.GetExecutingAssembly()
        .GetTypes()
        .SelectMany(/* ... */)
        .GroupBy(x => x.Key, x => x.Value)
        .ToDictionary(g => g.Key, g => g.ToList());
    
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜