简体   繁体   中英

Dictionary with a key of interface type, get keys where interface is implemented

I have a dictionary of interface types and Func . ( IBase is the base of IA , IB and IC )

var _dictionary =
    new Dictionary<Type, Func<IBase, IEnumerable<IResult>>>
    {
        {typeof(IA), p => _mapper.Map(p as IA)},
        {typeof(IB), p => _mapper.Map(p as IB)},
        {typeof(IC), p => _mapper.Map(p as IC)}
    };

Passing a concrete instance of IA (or IB etc) into a method, how do I get the Func corresponding to the matching interface the instance implements:

public IEnumerable<IResult> Resolve(IBase theInstance)
{
    // This fails because theInstance.GetType() result, is not the interface type
    if (!_dictionary.TryGetValue(theInstance.GetType(), out var func)) return Enumerable.Empty<IResult>();

    var result = func.Invoke(theInstance);

    return result;
}

I'm trying to avoid using a switch statement of each of the interface types.

Type exposes a GetInterfaces() Method which returns all interfaces implemented by the Type.

If your types only implement one interface this may work, but if more are implemented you may need to rework the solution. Perhaps a factory which will return a mapper for the specified Interface type?

Related reading: https://docs.microsoft.com/en-us/dotnet/api/system.type.getinterfaces?view=netframework-4.7.2

This won't work because the dictionary type does not match the instance type.

If you inspect your dictionary, you will find that the type being stored as a key is that of the interface:

{Name = "IA" FullName = "SomeNameSpace.IA"}

So when you try to get the value using the type of the instance , there is no match and it fails.

If you wanted this to work, you would need to register the type of the instance in your dictionary for proper resolution:

var _dictionary = new Dictionary<Type, Func<IBase, IEnumerable<IResult>>>
{
    {typeof(IA), p => _mapper.Map(p as IA)},
    {typeof(IB), p => _mapper.Map(p as IB)},
    {typeof(IC), p => _mapper.Map(p as IC)},
    //This would make it work
    {typeof(SomeInstanceType), p=> _mapper.Map(p as IA) }
};

This is obviously not very practical.

What you can do instead, is try to figure out if the type implements one of the interfaces your dictionary accounts for:

var interfaces = theInstance.GetType().GetInterfaces();
var key = _dictionary.Keys.Where(k => interfaces.Contains(k)).FirstOrDefault();

if (key == null) 
    return Enumerable.Empty<IResult>();

var map= _dictionary[key];
var result = map(theInstance);
return result;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM