C# 为什么我的类型没有标记为相等?
关于这一点,还有其他一些问题,但我觉得没有一个真正提供了可靠的答案 我最近经常搞反射,我想检查一些实现特定接口的程序集中包含的类型 所以我有一个名为BESCollector的类,它实现了ICollectorC# 为什么我的类型没有标记为相等?,c#,reflection,types,interface,C#,Reflection,Types,Interface,关于这一点,还有其他一些问题,但我觉得没有一个真正提供了可靠的答案 我最近经常搞反射,我想检查一些实现特定接口的程序集中包含的类型 所以我有一个名为BESCollector的类,它实现了ICollector public class BESCollector : ICollector { // ... } public interface ICollector { IDbRelay DbRelay { get; set; } ILogManager LogManager {
public class BESCollector : ICollector
{
// ...
}
public interface ICollector
{
IDbRelay DbRelay { get; set; }
ILogManager LogManager { get; set; }
void Init(ILogManager logManager, IDbRelay dbRelay);
void Execute();
}
在这里,我加载程序集,遍历所有类型,并查看该类型是否包含ICollector类型的接口
Assembly pluginAssembly = Assembly.ReflectionOnlyLoadFrom(pluginConfig.AssemblyLocation);
IEnumerable<Type> types = pluginAssembly.GetTypes().Where(t => t.GetInterfaces().Contains(typeof(ICollector)));
我调用的.GetInterfaces()
类型显然是:
- interfaces {System.Type[1]} System.Type[]
+ [0] {Name = "ICollector" FullName = "SquidReports.DataCollector.Interface.ICollector"} System.Type {System.ReflectionOnlyType}
+ type {Name = "BESCollector" FullName = "SquidReports.DataCollector.Plugin.BES.BESCollector"} System.Type {System.ReflectionOnlyType}
但是等式语句interfaces.Contains(typeof(ICollector))
的计算结果永远不会为true
您认为我没有混淆这里的类型,当我在调试时将鼠标移到(typeof(ICollector))
上时,它会清楚地显示SquidReports.DataCollector.Interface.ICollector
当然,这确实有效:
Type[] interfaces = type.GetInterfaces();
if (interfaces.Any(t => t.Name == typeof(ICollector).Name))
{
Console.WriteLine(@"\o/");
}
但这并没有告诉我很多,除了相同名字的类型
此外,为什么这项检查失败
if (typeof(ICollector).Equals(typeof(ICollector)))
{
Console.WriteLine("EQUALIZED");
}
为什么我的第一次平等检查失败了?更具体地说,类型平等在C#5.0中是如何工作的?对于“Type”类型,是否没有为.Equals()实现任何特定内容
编辑:
在I Quality Catalyst的要求下,下面的Catalyst快速进行了一项测试,如果接口和类在同一个程序集中定义,那么等式的计算结果是否为true。这确实有效:
class Program
{
public interface ITest
{
}
public class Test : ITest
{
public int ID { get; set; }
}
static void Main(string[] args)
{
Type[] interfaces = (typeof(Test)).GetInterfaces();
if (interfaces.Any(t => t == typeof(ITest)))
{
Console.WriteLine(@"\o/");
}
}
}
EDIT2:下面是icCollector的实现
public class BESCollector : ICollector
{
// ...
}
public interface ICollector
{
IDbRelay DbRelay { get; set; }
ILogManager LogManager { get; set; }
void Init(ILogManager logManager, IDbRelay dbRelay);
void Execute();
}
然而,我相信我可能错过了一个重要的细节。我在这里处理三个程序集:
SquidReports.DataCollector
)程序集,我在其中执行相等性检查SquidReports.DataCollector.Interface
)程序集SquidReports.DataCollector.Plugin.BES
)程序集SquidReports.DataCollector.Interface
)是从ReflectionOnlyAssemblyResolve事件加载的,如下所示,因为ReflectionOnlyLoadFrom()不会自动解析依赖项:
public Assembly ReflectionOnlyAssemblyResolve(object sender, ResolveEventArgs args)
{
// This event is used to resolve dependency problems. We need to return the requested assembly in this method.
// We should probably look in two locations:
// 1. The SquidReports.DataCollector folder
// 2. The Corresponding folder in SquidReports.DataCollector\Plugins
// Let's first turn the 'full' assembly name into something more compact
AssemblyName assemblyName = new AssemblyName(args.Name);
this.Logger.LogMessage(LogLevel.Debug, String.Format("Attempting to resolve Assembly {0} to load {0}", assemblyName.Name, args.RequestingAssembly.GetName().Name));
// Let's also get the location where the requesting assembly is located
DirectoryInfo pluginDirectory = Directory.GetParent(args.RequestingAssembly.Location);
string assemblyFileName = String.Format("{0}.dll", assemblyName.Name);
if (File.Exists(assemblyFileName))
{
// It's in the main bin folder, let's try to load from here
return Assembly.ReflectionOnlyLoadFrom(assemblyFileName);
}
else if (File.Exists(Path.Combine(pluginDirectory.FullName, assemblyFileName)))
{
// It's in the plugin folder, let's load from there
return Assembly.ReflectionOnlyLoadFrom(Path.Combine(pluginDirectory.FullName, assemblyFileName));
}
return null;
}
EDIT3:根据下面Joe的建议,我使用以下命令再次调试了应用程序:
if (type.Name == "BESCollector")
{
Type[] interfaces = type.GetInterfaces();
Type interface1 = interfaces[0];
Type interface2 = typeof(ICollector);
Console.WriteLine("");
}
我复制了interface1
和interface2
的完整属性,然后将它们放入一个不同的文件中
我认为,结果可能解决了我的问题:
接口1
描述如下:
interface1 {Name = "ICollector" FullName = "SquidReports.DataCollector.Interface.ICollector"} System.Type {System.ReflectionOnlyType}
而接口2
的描述如下:
interface2 {Name = "ICollector" FullName = "SquidReports.DataCollector.Interface.ICollector"} System.Type {System.RuntimeType}
那么,我假设问题是因为{System.RuntimeType}!={System.ReflectionOnlyType},而这个Assembly.ReflectionOnlyLoadFrom()应该对此负责吗?多亏了乔·恩兹明格,我才偶然发现了答案: 看起来,由于我使用的是
Assembly.ReflectionOnlyLoadFrom()
,因此从程序集中加载的类型实际上是System.ReflectionOnlyType,而不是System.RuntimeType
基本上,有一个简单且非常酷的解决方案:
这应该可以解决您的问题:)您的相等性检查是否可以与同一程序集中定义的任何其他接口一起工作?@Quality Catalyst:事实上,这似乎确实有效,请参阅上面的更新。我不太明白。你能给我们看一下'ICollector'的声明吗?@RobinMattheussen是与接口在同一程序集中的派生类吗?让我们来看看。比较GUID的好主意。