2010-02-21 14 views
5

Mein erstes Ziel ist es, die Typen auf einer bestimmten Schnittstelle mit einem generischen zu filtern.Wie spiegelt man Typen, die eine Schnittstelle von generischen haben, und erhalten diese Art von generischen

Mein zweites Ziel ist es, den Typ des generischen Parameters selbst zu erhalten.

public UserService : IUserService, IDisposable, IExportableAs<IUserService> 
{ 
    ... 
} 

Ich kann nicht die Struktur der Klasse, ihre Schnittstellen (wenn überhaupt) oder ähnliches annehmen. Die einzige Sache, die ich weiß, ziele ich ExportableAs<T> von meiner geteilten Versammlung, die verwendet wurde, um dieses Plugin zu erstellen. Aber ich muss den Typ dynamisch registrieren.

Also verwende ich eine generische Schnittstelle, um den zu exportierenden Typ zu markieren. In diesem Fall ist es IUserService. Ich mache das unter der Annahme, dass eine raffinierte Linq-Abfrage mir geben kann, was ich will. Aber ich habe ein paar Probleme.

Hier ist, was ich bisher:

assembly.GetTypes() 
    .Where(t => t.GetInterfaces().Any(i => 
       i.IsGenericType && 
       i.GetGenericTypeDefinition() == typeof(IExportableAs<>)) 
      ).ToList() 
    .ForEach(t => _catalogs.Add(
      new ComposablePart() 
      { 
       Name = t.FullName, 
       Type = t // This is incorrect 
      }) 
     ); 

Dies funktioniert, aber beachten Sie den Kommentar oben für „Das ist falsch“. Dieser Typ ist die abgeleitete Klasse UserService.

Was ich in meinem Endergebnis benötigen, sind:

  • Der generische Typ der IExportableAs<T> gehen in (IUserService in diesem Fall)
  • Die abgeleitete Klasse-Typ (in diesem Fall UserService)

Diese Frage bekam eine gute Abstimmung, da sie mir nahe kam (wie Sie oben sehen können): How to determine if a type implements a specific generic interface type Aber ich muss einen Schritt weiter gehen, um diesen generischen Typ zu finden.

Fühlen Sie sich frei, meine linq oben zu beschädigen.

Vielen Dank im Voraus!

Antwort

4

Verstanden

assembly.GetTypes().SelectMany(t => t.GetInterfaces(), (t, i) => new { t, i }) 
    .Where(ti => ti.i.IsGenericType && 
       ti.i.GetGenericTypeDefinition() == (typeof(IExportableAs<>))) 
    .Select(ti => new ComposablePart() { 
     Name = ti.t.FullName, 
     Type = ti.i.GetGenericArguments()[0] 
    }); 

[Bearbeiten] In meiner Aufregung, ich habe nicht verlassen mein Testprogramm läuft lange genug, um eine Ausnahme auf der Schnittstelle zu werfen, die nicht generisch war. Dachte das .NET Framework sei dort besonders clever gewesen. Korrigierter Code jetzt, da ich weiß, dass es nicht ist.

+0

Interessant. Verwenden eines anonymen Typs zum Erstellen eines Objekts. Das hat ein Versprechen. +1 – eduncan911

+0

Ja, das war es. Beachten Sie jedoch, dass Sie in der Select() - Klausel einen zweiten anonymen Typ erstellen. Es sollte sein: '.Wählen Sie (ti => neues ComposablePart() {Name = ti.t.FullName, Type = ti.i.GetGenericArguments() [0]});' Andernfalls wird es nicht in ein bekanntes konvertiert Geben Sie eine ToList() ein. – eduncan911

+0

Ich habe jedoch eine Sorge mit dem 'GetGenericTypeDefinition() [0]' Index. Dies beschränkt mich auf nur 1 IEExportableAs <> 'korrekt? – eduncan911

Verwandte Themen