【问题标题】:Compare generic-interface-type to given type将通用接口类型与给定类型进行比较
【发布时间】:2018-11-08 01:14:57
【问题描述】:

我正在尝试动态创建一个继承自泛型 interface 的类型的实例。

例如,我有以下基本接口,其中几个其他接口派生自:

public interface IDummy { }

我有两个派生接口:

public interface IDummyDerived<T> : IDummy
{
  void Foo(T value);
}

public interface ITempDerived<T> : IDummy
{
  void HelloWorld(T value);
}

现在我需要一个 ServiceProvider-Class,我可以在其中创建找到实现给定接口的类。每个接口(IDummyDerived 和 ITempDerived)只实现一次。

我的做法是:

internal class DummyServiceProvider
{
  public T GetDummy<T>() where T : IDummy
  {
    Type baseType = typeof(IDummy);
    Type[] types = AppDomain.CurrentDomain.GetAssemblies().SelectMany(a => a.GetTypes()).Where(p => baseType.IsAssignableFrom(p) && p.IsClass).ToArray();
    //now I have all classes which implements one of my interfaces
    foreach(Type type in types)
    {
      // here I want to check if the current type is typeof(T)
      // (typeof(T) == type) ->  doesn't work
      // (type.GetGenericTypeDefinition() == type) doesnt work

    }
  }
  return default(T);
}

如何正确地将给定的typeof(T) 与类型数组中的类型进行比较?

-- 更新:

DummyServiceProvider 的用法如下:

IDummyDerived&lt;string&gt; dummyDerived = myDummyServiceProvider.GetDummy&lt;IDummyDerived&lt;string&gt;&gt;()

【问题讨论】:

  • 我看到了IDummyDerived&lt;T&gt; 的定义,但没有看到IDummyDerived 的定义。如果没有IDummyDerived 的定义,代码将无法编译并且应该将编译错误抛出为Using the generic type 'IDummyDerived&lt;T&gt;' requires 1 type arguments。您的问题是否缺少一些代码?
  • 抱歉,在调用服务提供者时忘记了泛型
  • 请查看发布的答案。

标签: c# reflection types


【解决方案1】:

您正在检查 base generic interface typederived type 之间的相等性,这始终是错误的:

看下面的代码

using System;
using System.Reflection;
using System.Linq;

namespace AssemblyLoadRefelectionExp
{
    public class MyClass
    {
        public string Key { get; set; }
    }

    public interface IDummy { }

    public interface IDummyDerived<T> : IDummy
    {
        void Foo(T value);
    }

    public interface ITempDerived<T> : IDummy
    {
        void HelloWorld(T value);
    }

    public class DummyDerived<T> : IDummyDerived<T>
    {
        public void Foo(T value)
        {
            Console.WriteLine("DummyDerived`1 ->Foo");
        }
    }

    public class AnotherDummy : IDummyDerived<string>
    {
        public void Foo(string value)
        {
            Console.WriteLine("AnotherDummy -> Foo");
        }
    }

    public class Program
    {
        public static void Main()
        {
            Console.WriteLine($"Is {typeof(DummyDerived<MyClass>)} equal to {typeof(IDummyDerived<MyClass>)} : {CheckType<DummyDerived<MyClass>>(typeof(IDummyDerived<MyClass>))}");
            Console.WriteLine("---------------------------------");
            GetDummy<IDummyDerived<string>>();

            Console.ReadLine();
        }

        public static bool CheckType<T>(Type type)
        {
            return typeof(T) == type ? true : false;
        }

        public static T GetDummy<T>() where T : IDummy
        {
            Type baseType = typeof(IDummy);
            Type[] types = AppDomain.CurrentDomain.GetAssemblies().SelectMany(a => a.GetTypes()).Where(p => baseType.IsAssignableFrom(p) && p.IsClass).ToArray();
            //now I have all classes which implements one of my interfaces
            foreach (Type type in types)
            {
                Console.WriteLine($"Is {type.Name} assignable from {typeof(T)} : {typeof(T).IsAssignableFrom(type)}");
            }

            return default(T);
        }
    }
}

产生的输出为

Is AssemblyLoadRefelectionExp.DummyDerived1[AssemblyLoadRefelectionExp.MyClass] equal to AssemblyLoadRefelectionExp.IDummyDerived1[AssemblyLoadRefelectionExp.MyClass] : False`


Is DummyDerived1 assignable from AssemblyLoadRefelectionExp.IDummyDerived1[System.String] : False

是否可以从 AssemblyLoadRefelectionExp.IDummyDerived`1[System.String] 分配 AnotherDummy :True

如果你签入上面的代码,为了检查基类型和派生类型,我在这里使用了IsAssignableFrom 方法,因为GetDummy 方法是用base generic interface type 调用的。 IsAssignableFrom 验证可以将指定类型的实例分配给当前类型的实例。

【讨论】:

    【解决方案2】:

    一个更简单的解决方案是重写你的 where 如下

    string nameOfIDummy = typeof(IDummy).Name;
    string nameOfT = typeof(T).Name;
    IEnumerable<Type> classTypes = AppDomain.CurrentDomain.GetAssemblies().SelectMany(a => a.GetTypes()).Where(p => p.IsClass && p.GetInterface(nameOfIDummy) != null && p.GetInterface(nameOfT ) != null);
    

    也许你可以写你需要的东西,我不明白用例,对我来说这似乎是一件奇怪的事情。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-01-31
      • 2023-03-29
      • 2019-05-28
      • 2015-10-25
      • 2023-03-16
      • 1970-01-01
      • 1970-01-01
      • 2013-09-14
      相关资源
      最近更新 更多