【问题标题】:Comparing type discovered through reflection with referenced type in .NET将通过反射发现的类型与 .NET 中的引用类型进行比较
【发布时间】:2021-08-24 20:07:55
【问题描述】:

最终目标:我正在实现一个服务器应用程序和协议,并希望允许插件能够处理任意数量的请求命令。为此,我在 dll 中创建了一个接口(我们将其称为 IHandler)。其他用户将引用它并实现接口以创建他们的各种处理程序。例如:public class BlergHandler : IHandler

他们创建的 dll 将被放置在一个公共目录中,并且在启动时服务器应用程序将通过反射加载所有 dll。当请求进来时,它将启动所需的处理程序并传递请求。

我遇到的问题是我无法确定使用反射找到的类型是否实现了接口。我相信这个问题与将通过反射加载的类型接口与直接引用的接口进行比较有关。这是我暂时使用的代码:

var DLL = Assembly.LoadFile(filename);

foreach (Type type in DLL.GetExportedTypes())
{
  // dynamic c = Activator.CreateInstance(type);
  if (!type.IsInterface)
  {
    Console.Write("Found: " + type.Name);
    if (type.GetInterfaces().Contains(typeof(IHandler)))
    {
      Console.Write("  : IHandler (contains check)");
    }
    
    if (typeof(IHandler).IsAssignableFrom(type))
    {
      Console.Write("  : IHandler (assignable check)");
    }
    Console.WriteLine(""); // For cleanliness
  }
}

即使找到的类型实现了相关接口,上述检查也会失败。我还确认,如果我直接引用 dll,则检查通过。例如TestHandler.GetInterfaces().Contains(IHandler) 是真的。

我希望我能很好地解释我想要发生的事情以及实际发生的事情。我必须错过一些简单的东西,但我被卡住了。提前感谢你们光荣的巫师!

对我有用的解决方案:

经过深入研究,问题似乎与在与 IHandler 接口相同的项目中实现我的测试处理程序有关。 .NET 似乎不会将我的应用程序中直接引用的 dll 版本与使用反射加载的相同 dll 等同起来。

我的解决方案是让 IHandler 接口 dll 成为它自己的库,并在另一个 dll 中实现我的测试处理程序(无论如何,这更符合最终目标)。我的项目和 handlers dll 都引用了 IHandler 接口,但是我的应用程序不再直接引用 handlers dll。

我将把这个打开一点来尝试@DevRacker 引用的解决方案。我使用的是旧版本的 .NET(不是 5.0),所以我不确定它是否适合我的情况。

【问题讨论】:

  • 这是.net框架?什么版本?
  • 也许你正在做相反的事情。你试过type.GetType().IsAssignableFrom(typeof(IHandler))吗?
  • @DevRacker 是的,.NET Framework 4.7.2,虽然我没有与任何特定版本结婚。

标签: c# .net reflection


【解决方案1】:

我认为在这种情况下比较类型的方法不是最好的方法,最好将名称作为字符串比较并使用Activator.CreateInstance()确认。

这是您为此更新的代码(使用 .NET 5):

var DLL = Assembly.LoadFile(@"");
foreach (Type type in DLL.GetExportedTypes())
{
    if (!type.IsInterface)
    {
        Console.Write("Found: " + type.Name);
        if (type.GetInterfaces().Any(t => t.AssemblyQualifiedName == typeof(IHandler).AssemblyQualifiedName))
        {
            var instance = Activator.CreateInstance(type) as IHandler;
            if (instance != null)
            {
                Console.Write("  : IHandler (contains check)");
            }
        }            
        Console.WriteLine(""); // For cleanliness
    }
}

您可以使用AssemblyQualifiedNameName,这完全取决于版本是否必须相同。 Activator 确保您能够将类的实例创建为该接口,这是 100% 安全的,因为否则无法创建实例。

【讨论】:

  • 谢谢!我会试试这个。我实际上找到了 a 解决方案,同时挖掘了更多内容并弄乱了一些东西。我直接引用了 IHandler 项目,但也实现了一些“默认”处理程序并在运行时加载 dll。出于某种原因,.NET 似乎将其“视为”两个独立的接口。
猜你喜欢
  • 2018-11-08
  • 1970-01-01
  • 1970-01-01
  • 2023-03-16
  • 2015-01-31
  • 2012-02-08
  • 1970-01-01
  • 2023-03-29
  • 1970-01-01
相关资源
最近更新 更多