Ci sono alcune altre domande riguardo a questo su SO, ma ho sentito nessuno di loro ha davvero fornito una risposta solida.Perché i miei tipi non sono contrassegnati come uguali?
Ultimamente sto riflettendo molto con la riflessione e volevo controllare i tipi contenuti in alcuni assembly che implementano una determinata interfaccia.
quindi ho una classe chiamata BESCollector che implementa ICollector
public class BESCollector : ICollector
{
// ...
}
Qui ho caricare l'assembly, ciclo attraverso tutti i tipi e vedere se questo tipo contiene un'interfaccia di tipo ICollector ...
Assembly pluginAssembly = Assembly.ReflectionOnlyLoadFrom(pluginConfig.AssemblyLocation);
IEnumerable<Type> types = pluginAssembly.GetTypes().Where(t => t.GetInterfaces().Contains(typeof(ICollector)));
... che non produce risultati :(Durante il debug, posso vedere chiaramente che esso contiene questo tipo. Mi interrompo sull'i-loop
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/");
}
}
Questi risultati sono direttamente dal debugger. Qui si può vedere che interfaces
contiene un unico tipo, vale a dire ICollector:
- interfaces {System.Type[1]} System.Type[]
+ [0] {Name = "ICollector" FullName = "SquidReports.DataCollector.Interface.ICollector"} System.Type {System.ReflectionOnlyType}
e il tipo sto chiamando .GetInterfaces()
su è chiaramente BESCollector:
+ type {Name = "BESCollector" FullName = "SquidReports.DataCollector.Plugin.BES.BESCollector"} System.Type {System.ReflectionOnlyType}
Ma l'affermazione dell'uguaglianza interfaces.Contains(typeof(ICollector))
mai restituisce true .
Solo così pensi che non sto mescolando i tipi qui, quando eseguo il mouse su (typeof(ICollector))
durante il debug, visualizza chiaramente SquidReports.DataCollector.Interface.ICollector
.
Questo, naturalmente, funziona:
Type[] interfaces = type.GetInterfaces();
if (interfaces.Any(t => t.Name == typeof(ICollector).Name))
{
Console.WriteLine(@"\o/");
}
Ma che does't dimmi un bel po ', oltre al fatto che i tipi con lo stesso nome.
Inoltre, perché questo controllo fallisce?
if (typeof(ICollector).Equals(typeof(ICollector)))
{
Console.WriteLine("EQUALIZED");
}
Perché il primo controllo di uguaglianza non riesce? Più specificamente, come funziona l'uguaglianza di tipo in C# 5.0? Non è stato implementato nulla di specifico per .Equals() per il tipo "Tipo"?
EDIT:
Su richiesta di I Qualità Catalyst seguito rapidamente ha fatto un test, se l'uguaglianza sarebbe valutato come vero se l'interfaccia e la classe sono stati definiti nello stesso assembly. Questo funziona:
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: Ecco l'implementazione di ICollector
public interface ICollector
{
IDbRelay DbRelay { get; set; }
ILogManager LogManager { get; set; }
void Init(ILogManager logManager, IDbRelay dbRelay);
void Execute();
}
Tuttavia, credo forse ho perso su un dettaglio importante.Sto lavorando con tre Assemblee qui:
- 'PRINCIPALE' (
SquidReports.DataCollector
) assemblaggio dove sto facendo il controllo di uguaglianza - L' 'interfaccia' (
SquidReports.DataCollector.Interface
) assembly che contiene ICollector - Il ' Plugin' (
SquidReports.DataCollector.Plugin.BES
) assembly che contiene la definizione di BESCollector
probabilmente è molto importante notare che il 'Interface' (SquidReports.DataCollector.Interface
) viene caricata dall'evento ReflectionOnlyAssemblyResolve, come mostrato di seguito, perché ReflectionOnlyLoadFrom() non risolve automaticamente le dipendenze:
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: Su suggerimento di Joe di seguito, ho il debug l'applicazione di nuovo di utilizzare questo:
if (type.Name == "BESCollector")
{
Type[] interfaces = type.GetInterfaces();
Type interface1 = interfaces[0];
Type interface2 = typeof(ICollector);
Console.WriteLine("");
}
Ho copiato il completa le proprietà di interface1
e interface2
, quindi le ha lanciate in un file diff.
Il risultato, credo, potrebbe essere risolto il mio problema:
interface1
è descritto come segue:
interface1 {Name = "ICollector" FullName = "SquidReports.DataCollector.Interface.ICollector"} System.Type {System.ReflectionOnlyType}
Mentre interface2
è descritto in questo modo:
interface2 {Name = "ICollector" FullName = "SquidReports.DataCollector.Interface.ICollector"} System.Type {System.RuntimeType}
Così sono io corretto assumendo che il problema sia causato perché {System.RuntimeType}! = {System.ReflectionOnlyType}, e che Assembly.ReflectionOnlyLoadFrom() è per b zoppo per questo?
Il controllo di uguaglianza funziona con qualsiasi altra interfaccia definita nello stesso assembly? –
@Catalyst qualità: in realtà sembra funzionare, vedere il mio aggiornamento sopra. Non seguo abbastanza qui. –
Puoi anche mostrarci la dichiarazione di "ICollector" per favore? –