首页 > 解决方案 > 使用反射查找接口在装配类型中

问题描述

我不确定是否是尖括号导致了我的问题,但我无法在 Stack Overflow 的答案中找到答案。如果已经有一个,我欢迎你指出我正确的方向。

总而言之,我有一个接口,我无法通过反射找到它。让我们设置舞台:

接口

interface ICrew
{
    string Name { get; set; }
}

interface IDataService<T>
{
    IEnumerable<T> GetItems();
}

课程

class Crew : ICrew
{
    public string Name { get; set; }
}

class CrewRepository : IDataService<ICrew>
{
    DbContext _context { get; }

    public CrewRepository(DbContext context)
    {
        _context = context;
    }


    public IEnumerable<ICrew> GetItems()
    {
        return _context.Crews;
    }
}

class DbContext
{
    public DbContext()
    {
        Crews = new List<Crew>();
    }
        
    public List<Crew> Crews;
}

代码

class Program
{
    private static DbContext _context;

    static void Main(string[] args)
    {
        _context = new DbContext();

        //I want to find CrewRepository (which is type of IDataService<ICrew>)
        var dataService = Get(typeof(ICrew));
    }

    private static object Get(Type T)
    {
        var types = typeof(CrewRepository).Assembly.GetTypes();

        var test = types.Where(t => t.IsAssignableFrom(T)); //Finds ICrew

        var test2 = types.Where(t => t.GetInterfaces().Contains(T)); //Finds Crew

        var test3 = types.Where(t => t.GetInterfaces().Contains(typeof(IDataService<>))); //Finds nothing

        var test4 = types.Where(t => t.IsAssignableFrom(typeof(IDataService<>))); //Finds interface IDataService

        var test5 = types.Where(t => typeof(IDataService<>).IsAssignableFrom(t)); //Finds interface IDataService

        var instance = types
            .Where(t => t.IsAssignableFrom(T))
            .FirstOrDefault();

        if (instance != null)
        {
            return Activator.CreateInstance(instance, _context);
        }

        return default;
    }

}

我不知道如何正确查询程序集类型以获取IDataService<T>. 我的Get方法直到运行时才知道它会被要求什么类型,并且只有在编译时知道类型时才能使用尖括号内的泛型。谁能帮我弄清楚我应该在这里做什么才能Get通过使用反射返回我希望的正确类存储库?

标签: c#reflection

解决方案


正如评论中提到的,必须使用该Type.MakeGenericType方法在运行时创建所需的类型IDataService<"T">。您的Get方法可能如下所示:

private static object Get(Type t)
{
    var types = typeof(CrewRepository).Assembly.GetTypes();
    var runtimeType = typeof(IDataService<>).MakeGenericType(t);
    var type = types.SingleOrDefault(x => x.GetInterfaces().Contains(runtimeType));

    if (type != null)
    {
        return Activator.CreateInstance(type, _context);
    }

    return null;
}

演示:https ://dotnetfiddle.net/vRJzr8


推荐阅读