简体   繁体   中英

How to use reflection to get implementations of a generic interface

  • I have a generic interface that requires a read and key method. I want to use reflection to get an instance of each implementation.
  • Once I have a the implementation, I want to get it's key and store the key and the instance in a dictionary.
  • Eventually, I would have a method where I pass in a key and byte[], it would look the key up in the dictionary and use the instance that it retrieves to read the byte[] and return an object .
  • I hope this is understandable, if not I can answer questions in the comments.
  • This example only has int and string, but I'll have many more types in my real implementation.

The Goal

To have a dictionary with 2 entries stored as such:

  • 43, IRead<int> new Reader()
  • 61, IRead<string> new Reader()

public interface IRead<T>
{
    T Read(bool[] binary);
    int Key( T type );
}

public class Reader : IRead<int>, IRead<string>
{
    int IRead<int>.Read( byte[] binary )
    {
        // does stuff
        returns 4;
    }

    public int Key( int type ) { return 43; }

    string IRead<string>.Read( byte[] binary )
    {
        // does stuff
        returns "example";
    }

    public int Key( string type ) { return 61; }

    static StreamProcessor( )
    {
        // Here I want to get the definitions
    }
}

Please, when you ask a question, post code that compiles . It makes life easier for everyone (perhaps your answer is because the pseudocode you wrote is wrong?)

In any case, this will get all types which implement IRead<> :

var types = GetType().Assembly.GetTypes()
.Select(t => new
{
    Type = t,
    MatchingInterfaces = t.GetInterfaces()
                          .Where(i => i.GetGenericTypeDefinition() == typeof(IRead<>))
})
.Where(t => t.MatchingInterfaces.Any())

Your pre-requisite of returning the key doesn't make that much sense. You can't find all instances of IRead<> . And you need an instance to give you a key.

For example, what would your dictionary look like if you had this code:

var readerOne = new Reader();
var readerTwo = new Reader();

Which instance goes into the dictionary?

The closest you can get is to:

  1. Pass the method a list of objects and return the key of those instances
  2. Create a dummy instance of each type to get the key
  3. Make the key method static, and not part of the interface.

I suggest breaking this up because there are a few different things you're trying to do - some are clear, some aren't.

First you want to get types that implement IReader:

public IEnumerable<Type> GetTypes<TAssignableFrom>()
{
    return this.GetType().Assembly.GetTypes()
        .Where(type => type.IsAssignableFrom(typeof (TAssignableFrom)));
}

What do you want to do with those types? If you want to create an instance of each type then either they need to have parameterless constructors or otherwise identical constructors, or you'd need to be using some dependency injection container.

Let's say that they're going to have parameterless constructors. We can update the above to

public IEnumerable<Type> GetTypes<TAssignableFrom>()
{
    return this.GetType().Assembly.GetTypes()
        .Where(type => type.IsAssignableFrom(typeof (TAssignableFrom))
            && type.GetConstructor(Type.EmptyTypes) != null
        );
}

Now you've got a bunch of types that you can instantiate.

From there it gets pretty fuzzy. What will you do with those types? It's not much use to put them into a dictionary because they are all different types.

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