507 Stimmen

Kann eine anonyme Klasse ein Interface implementieren?

Ist es möglich, dass ein anonymer Typ ein Interface implementiert?

Ich habe einen Codeabschnitt, der funktionieren soll, aber weiß nicht, wie das geht.

Ich habe ein paar Antworten erhalten, die entweder nein sagen oder eine Klasse erstellen, die das Interface implementiert, um neue Instanzen davon zu erstellen. Das ist nicht wirklich ideal, aber ich frage mich, ob es einen Mechanismus gibt, um eine schlanke dynamische Klasse über einem Interface zu erstellen, das dies einfacher macht.

public interface DummyInterface
{
    string A { get; }
    string B { get; }
}

public class DummySource
{
    public string A { get; set; }
    public string C { get; set; }
    public string D { get; set; }
}

public class Test
{
    public void WillThisWork()
    {
        var source = new DummySource[0];
        var values = from value in source
                     select new
                     {
                         A = value.A,
                         B = value.C + "_" + value.D
                     };

        DoSomethingWithDummyInterface(values);

    }

    public void DoSomethingWithDummyInterface(IEnumerable values)
    {
        foreach (var value in values)
        {
            Console.WriteLine("A = '{0}', B = '{1}'", value.A, value.B);
        }
    }
}

Ich habe einen Artikel gefunden Dynamic interface wrapping, der einen Ansatz beschreibt. Ist das der beste Weg, um dies zu tun?

1 Stimmen

Link scheint veraltet zu sein, dies könnte eine geeignete Alternative sein liensberger.it/web/blog/?p=298.

2 Stimmen

Ja, Sie können dies mit .NET 4 und höher (über das DLR) mithilfe des ImpromptuInterface NuGet-Pakets tun.

1 Stimmen

@PhilCooper Dein Link war wahrscheinlich seit mindestens 2016 nicht verfügbar, aber zum Glück wurde er vorher archiviert. web.archive.org/web/20111105150920/http://www.liensberger.it‌​/…

388voto

HasaniH Punkte 7873

Nein, anonyme Typen können kein Interface implementieren. Gemäß dem C#-Programmierhandbuch:

Anonyme Typen sind Klassentypen, die aus einem oder mehreren öffentlichen schreibgeschützten Eigenschaften bestehen. Keine anderen Arten von Klassenmitgliedern wie Methoden oder Ereignisse sind erlaubt. Ein anonymer Typ kann nicht in ein Interface oder einen Typ außer object umgewandelt werden.

7 Stimmen

Es wäre sowieso schön, dieses Zeug zu haben. Wenn es um die Lesbarkeit von Code geht, sind Lambda-Ausdrücke normalerweise nicht der richtige Weg. Wenn wir über RAD sprechen, stehe ich total auf eine javanische anonyme Schnittstellenimplementierung. Übrigens ist dieses Feature in manchen Fällen mächtiger als Delegaten.

21 Stimmen

@ArsenZahray: Lambda-Ausdrücke erhöhen tatsächlich die Code-Lesbarkeit, wenn sie gut eingesetzt werden. Sie sind besonders leistungsstark, wenn sie in funktionalen Ketten verwendet werden, was den Bedarf an lokalen Variablen verringern oder sogar beseitigen kann.

4 Stimmen

Du könntest das so machen "Anonyme Implementierungsklassen - Ein Designmuster für C#" - twistedoakstudios.com/blog/…

96voto

Mia Clarke Punkte 7963

Während die Antworten im Thread alle wahr genug sind, kann ich es nicht lassen, Ihnen zu sagen, dass es tatsächlich möglich ist, eine anonyme Klasse ein Interface implementieren zu lassen, auch wenn es etwas kreatives Mogeln erfordert, um dahinzugelangen.

Im Jahr 2008 schrieb ich einen benutzerdefinierten LINQ-Provider für meinen damaligen Arbeitgeber, und an einem Punkt musste ich in der Lage sein, "meine" anonymen Klassen von anderen anonymen zu unterscheiden, was bedeutete, dass sie ein Interface implementieren mussten, das ich zum Typenüberprüfen verwenden konnte. Die Art und Weise, wie wir das gelöst haben, bestand darin, Aspekte zu verwenden (wir haben PostSharp verwendet), um die Interface-Implementierung direkt im IL hinzuzufügen. Also ist es tatsächlich möglich, dass anonyme Klassen Interfaces implementieren, man muss nur die Regeln etwas beugen, um dorthin zu gelangen.

9 Stimmen

@Gusdor, in diesem Fall hatten wir die vollständige Kontrolle über den Build, und er wurde immer auf einer dedizierten Maschine ausgeführt. Außerdem, da wir PostSharp verwendet haben und das, was wir taten, vollständig innerhalb dieses Rahmens legal war, konnte nichts wirklich schiefgehen, solange wir sicherstellten, dass PostSharp auf dem Build-Server installiert war.

16 Stimmen

@Gusdor Ich stimme zu, es sollte für andere Programmierer einfach sein, das Projekt zu bekommen und zu kompilieren, ohne große Schwierigkeiten zu haben, aber das ist ein anderes Problem, das separat angegangen werden kann, ohne vollständig auf Tools oder Frameworks wie postsharp zu verzichten. Das gleiche Argument, das du anführst, könnte auch gegen VS selbst oder jedes andere nicht standardmäßige MS-Framework erhoben werden, das nicht Teil des C#-Standards ist. Du benötigst diese Dinge, ansonsten "geht es schief". Das ist meiner Meinung nach kein Problem. Das Problem besteht darin, dass der Build so kompliziert wird, dass es schwerfällt, all diese Dinge richtig zusammenarbeiten zu lassen.

6 Stimmen

@ZainRizvi Nein, hat es nicht. Soweit ich weiß, ist es immer noch in Produktion. Die damals geäußerte Sorge erschien mir seltsam und willkürlich. Es hieß im Grunde "Verwenden Sie kein Framework, es wird alles kaputtgehen!". Das ist nicht passiert, nichts ist kaputtgegangen und ich bin nicht überrascht.

48voto

Arne Claassen Punkte 13640

Das Umwandeln anonymer Typen in Schnittstellen ist etwas, das ich mir schon seit einer Weile gewünscht habe, aber leider zwingt die aktuelle Implementierung Sie dazu, eine Implementierung dieser Schnittstelle zu haben.

Die beste Lösung dafür ist, eine Art dynamischen Proxy zu haben, der die Implementierung für Sie erstellt. Mit dem ausgezeichneten LinFu-Projekt können Sie ersetzen

select new
{
  A = value.A,
  B = value.C + "_" + value.D
};

mit

select new DynamicObject(new
{
  A = value.A,
  B = value.C + "_" + value.D
}).CreateDuck();

19 Stimmen

Impromptu-Interface-Projekt wird dies in .NET 4.0 mit dem DLR tun und ist leichter als Linfu.

0 Stimmen

Ist DynamicObject ein LinFu-Typ? System.Dynamic.DynamicObject hat nur einen geschützten Konstruktor (zumindest in .NET 4.5).

0 Stimmen

Ja. Ich bezog mich auf die LinFu-Implementierung von DynamicObject, die der DLR-Version vorausgeht.

16voto

Jason Bowers Punkte 496

Anonymous-Typen können über einen dynamischen Proxy Schnittstellen implementieren.

Ich habe eine Erweiterungsmethode auf GitHub geschrieben und einen Blog-Beitrag http://wblo.gs/feE veröffentlicht, um dieses Szenario zu unterstützen.

Die Methode kann folgendermaßen verwendet werden:

class Program
{
    static void Main(string[] args)
    {
        var developer = new { Name = "Jason Bowers" };

        PrintDeveloperName(developer.DuckCast());

        Console.ReadKey();
    }

    private static void PrintDeveloperName(IDeveloper developer)
    {
        Console.WriteLine(developer.Name);
    }
}

public interface IDeveloper
{
    string Name { get; }
}

13voto

Marc Gravell Punkte 970173

Nein, ein anonymer Typ kann nichts anderes tun, als einige Eigenschaften zu haben. Sie müssen Ihren eigenen Typ erstellen. Ich habe den verlinkten Artikel nicht im Detail gelesen, aber es scheint, dass er Reflection.Emit verwendet, um neue Typen "on the fly" zu erstellen; aber wenn Sie die Diskussion auf Dinge innerhalb von C# selbst beschränken, können Sie nicht das tun, was Sie wollen.

0 Stimmen

Und wichtig zu beachten: Eigenschaften können auch Funktionen oder Leershows (Action) enthalten: select new { ... MeinFunktion = new Func(s => value.A == s) } funktioniert, obwohl Sie auf neue Eigenschaften in Ihren Funktionen nicht verweisen können (wir können "A" nicht anstelle von "value.A" verwenden).

2 Stimmen

Nun, ist das nicht einfach eine Eigenschaft, die zufällig ein Delegierter ist? Es ist tatsächlich keine Methode.

1 Stimmen

Ich habe Reflection.Emit verwendet, um Typen zur Laufzeit zu erstellen, glaube aber jetzt, dass ich eine AOP-Lösung bevorzuge, um die Laufzeitkosten zu vermeiden.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X