Es gibt ein paar andere Fragen dazu auf SO, aber ich fühlte, dass keiner von ihnen wirklich eine solide Antwort lieferte.Warum werden meine Typen nicht als gleich gekennzeichnet?
Ich bin in letzter Zeit viel mit Reflektion herumalbern, und ich wollte nach Typen innerhalb einiger Assemblys suchen, die eine bestimmte Schnittstelle implementieren.
So habe ich eine Klasse namens BESCollector die ICollector implementiert
public class BESCollector : ICollector
{
// ...
}
Hier lade ich die Montage, eine Schleife durch alle Arten und sehen, ob diese Art eine Schnittstelle vom Typ ICollector enthält ...
Assembly pluginAssembly = Assembly.ReflectionOnlyLoadFrom(pluginConfig.AssemblyLocation);
IEnumerable<Type> types = pluginAssembly.GetTypes().Where(t => t.GetInterfaces().Contains(typeof(ICollector)));
..., die keine Ergebnisse :(ergibt. Während das Debuggen ich deutlich sehen, dass es diese Art enthält. ich breche auf dem if-Schleife
Assembly pluginAssembly = Assembly.ReflectionOnlyLoadFrom(pluginConfig.AssemblyLocation);
IEnumerable<Type> types = pluginAssembly.GetTypes().Where(t => t.GetInterfaces().Contains(typeof(ICollector)));
foreach (Type type in pluginAssembly.GetTypes())
{
Type[] interfaces = type.GetInterfaces();
if (interfaces.Contains(typeof(ICollector)))
{
Console.WriteLine(@"\o/");
}
}
Diese Ergebnisse stammen direkt vom Debugger. Hier können Sie sehen, dass interfaces
einen einzigen Typ enthält, nämlich ICollector:
- interfaces {System.Type[1]} System.Type[]
+ [0] {Name = "ICollector" FullName = "SquidReports.DataCollector.Interface.ICollector"} System.Type {System.ReflectionOnlyType}
Und die Typ-I-Aufruf bin .GetInterfaces()
auf deutlich BESCollector:
+ type {Name = "BESCollector" FullName = "SquidReports.DataCollector.Plugin.BES.BESCollector"} System.Type {System.ReflectionOnlyType}
Aber die Gleichheit Aussage interfaces.Contains(typeof(ICollector))
wertet nie wahr .
Nur damit Sie denken, ich bin nicht Typen hier zu vermischen, wenn ich Maus über (typeof(ICollector))
während des Debuggens, zeigt es deutlich SquidReports.DataCollector.Interface.ICollector
.
Dies ist natürlich funktioniert:
Type[] interfaces = type.GetInterfaces();
if (interfaces.Any(t => t.Name == typeof(ICollector).Name))
{
Console.WriteLine(@"\o/");
}
Aber die does't mir eine ganze Menge sagen, außer der Tatsache, dass die Typen mit dem gleichen Namen.
Außerdem, warum schlägt diese Überprüfung fehl?
if (typeof(ICollector).Equals(typeof(ICollector)))
{
Console.WriteLine("EQUALIZED");
}
Warum schlägt meine erste Gleichheitsprüfung fehl? Genauer gesagt, wie funktioniert Typgleichheit in C# 5.0? Wurde für .Equals() für den Typ "Type" nichts spezifisch implementiert?
EDIT:
Auf Wunsch von I Qualität Katalysator unten schnell einen Test hat, wenn die Gleichheit zu wahren bewerten würde, wenn die Schnittstelle und Klasse in der gleichen Baugruppe definiert wurden. Das funktioniert:
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: Hier ist die Implementierung von ICollector
public interface ICollector
{
IDbRelay DbRelay { get; set; }
ILogManager LogManager { get; set; }
void Init(ILogManager logManager, IDbRelay dbRelay);
void Execute();
}
Aber ich glaube, ich habe auf ein wichtiges Detail kann verpasst.Ich arbeite mit drei Baugruppen hier:
- Die 'Main' (
SquidReports.DataCollector
) Montage, wo ich die Gleichheitsprüfung - Die 'Schnittstelle' mache (
SquidReports.DataCollector.Interface
) Assembly, enthält ICollector - Die ' Plugin' (
SquidReports.DataCollector.Plugin.BES
) Assembly, die die Definition von BESCollector enthält
Es ist wahrscheinlich sehr wichtig zu beachten, dass die ‚Schnittstelle‘ (SquidReports.DataCollector.Interface
) wird aus dem Ereignis ReflectionOnlyAssemblyResolve geladen, wie unten gezeigt, weil ReflectionOnlyLoadFrom() nicht automatisch Abhängigkeiten löst:
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: unten Auf Anregung von Joe, ich gedebuggt die Anwendung erneut diese mit:
if (type.Name == "BESCollector")
{
Type[] interfaces = type.GetInterfaces();
Type interface1 = interfaces[0];
Type interface2 = typeof(ICollector);
Console.WriteLine("");
}
ich die kopierte vollständige Eigenschaften von interface1
und interface2
, dann warf diese in eine Datei diff.
Das Ergebnis, glaube ich, haben mein Problem gelöst:
interface1
wird wie folgt beschrieben:
interface1 {Name = "ICollector" FullName = "SquidReports.DataCollector.Interface.ICollector"} System.Type {System.ReflectionOnlyType}
Während interface2
wird wie folgt beschrieben:
interface2 {Name = "ICollector" FullName = "SquidReports.DataCollector.Interface.ICollector"} System.Type {System.RuntimeType}
ich so bin Korrekte Annahme, dass das Problem verursacht wird, weil {System.RuntimeType}! = {System.ReflectionOnlyType} und das Assembly.ReflectionOnlyLoadFrom() zu b ist lahm dafür?
Funktioniert Ihre Gleichheitsprüfung mit irgendeiner anderen Schnittstelle, die in der gleichen Versammlung definiert wird? –
@Quality Catalyst: Nun, eigentlich scheint das zu funktionieren, siehe mein Update oben. Ich folge hier nicht ganz. –
Können Sie uns bitte auch die Erklärung von 'ICollector 'zeigen? –