Laden...

Typen nach ihrem Aufbau vergleichen (um festzustellen, ob sich die Definition des Typs geändert hat)

Erstellt von Palladin007 vor 9 Jahren Letzter Beitrag vor 9 Jahren 2.247 Views
Palladin007 Themenstarter:in
2.079 Beiträge seit 2012
vor 9 Jahren
Typen nach ihrem Aufbau vergleichen (um festzustellen, ob sich die Definition des Typs geändert hat)

Hi,

ich möchte zwei Type-Objekte vergleichen, allerdings soll das nur den Typ und dessen Inhalt betrachten und sonst nichts weiter.

Als Beispiel:

public interface ITest
{
    string MyProperty { get; }
}

Und

public interface ITest
{
    string MyProperty { get; set; }
}

Ich möchte diese Beiden Typen vergleichen können und als Ergebnis erhalten, dass sie ungleich sind.

Der Hintergrund ist folgender:
Ich möchte zur Laufzeit Interfaces dynamisch implementieren. Nun würde das aber bei jedem Start passieren, daher speichere ich die erzeugten Implementierungen in eine Assembly.
Nun soll bei jedem Start geprüft werden, ob sich einer der Typen geändert hat. Wenn ja, wird die Implementierung angepasst und abgespeichert, andernfalls wird sie nur geladen.

Gibt es bereits etwas, was einen derartigen Vergleich ermöglicht?
Ich würde es gerne vermeiden, eine ganze Type-Definition darstellen zu müssen um die Typen zu vergleichen. In Mono.Cecil habe ich bisher auch keine überschaubare Möglichkeit gefunden, das zu realisieren.
Kennt jemand etwas, was entsprechende Funktionen bietet oder hat jemand eine Idee, wie ich das einfach selber realisieren kann?

Gruß

NuGet Packages im Code auslesen
lock Alternative für async/await

Beim CleanCode zählen nicht die Regeln, sondern dass wir uns mit diesen Regeln befassen, selbst wenn wir sie nicht befolgen - hoffentlich nach reiflichen Überlegungen.

849 Beiträge seit 2006
vor 9 Jahren

Hallo,

ich glaube ich würde nen Attribut mit ner Guid über die Typen und die implementierung hauen. Verschiedene Guid -> es hat sich etwas verändert. Kommt natürlich drauf an, wie Du diese Interfaces erzeugst.

Mich würde der Hintergrund interessieren.. Was treibt Dich dazu?

Palladin007 Themenstarter:in
2.079 Beiträge seit 2012
vor 9 Jahren

Es ist mal wieder nur eine Idee, die ich ausprobieren möchte.

Die Idee ist, den Code First Ansatz vom EF6 auf Interfaces zu übertragen in verbindung mit dem Repository-Pattern. Die tatsächliche Datenklasse sieht im Prinzip genauso aus, bei Mock-Varianten habe ich aber keine Validierung implizit mit dabei, da die vom EF geregelt wird.
Daher war der Gedanke, die Mock-Implementierung gleich mit generieren zu lassen (wenn denn gefordert) und dann dort die Validierung einzubauen.
Somit muss ich nur noch die Interfaces erstellen und der Rest passiert im Hintergrund.

Dazu wäre es dann auch möglich, für z.B. ein Plugin die Datenbank über das Repository zur Verfügung zu stellen. Das Plugin muss dann nur das Interface definieren und intern wird der Zugriff auf eine Datenbank geregelt.

Eine GUID würde ich gerne vermeiden, weil das für jede Änderung eine andere GUID bedeuten würde und wenn das einmal vergessen wird, funktioniert das ganze Konzept nicht mehr.

NuGet Packages im Code auslesen
lock Alternative für async/await

Beim CleanCode zählen nicht die Regeln, sondern dass wir uns mit diesen Regeln befassen, selbst wenn wir sie nicht befolgen - hoffentlich nach reiflichen Überlegungen.

S
145 Beiträge seit 2013
vor 9 Jahren

Ich würde die Schnittstelle von IEquatable noch mit ableiten

interface IMeinInterface: IEquatable

Die standard Listen zum Beispiel prüfen eigentlich erstmal ob entsprechendes Equals gesetzt ist bevor diese einen Referenzvergleich durchführen.

In der Equals Methode würde ich dann einfach die Eigenschaften/Felder beider Objekte prüfen.

Und für dich selbst könntest du dann einfach über Equals vergleichen.

(Achtung bei den Objekten welche deine Schnittstelle implementieren müsste eventuell dennoch GetHashCode und Equals überschrieben werden, bin mir da gerade nicht sicher)

Oder eventuell P.S. (hab das mit der implementierung falschv erstanden):
Eventuell hilft DuckTyping was, such mal bei googeln nach (bei Codeproject müsste da glaube was sein)

Palladin007 Themenstarter:in
2.079 Beiträge seit 2012
vor 9 Jahren

IEquatable hilft mir leider nicht weiter, da ich damit die Objekte vergleichen würde, nicht die Typen bzw. Interfaces.

Du sagst, DuckTyping könnte helfen, aber wie meinst du das?
DuckTyping würde sich auch auf die Objekte beziehen, die habe ich aber noch nicht.

NuGet Packages im Code auslesen
lock Alternative für async/await

Beim CleanCode zählen nicht die Regeln, sondern dass wir uns mit diesen Regeln befassen, selbst wenn wir sie nicht befolgen - hoffentlich nach reiflichen Überlegungen.

49.485 Beiträge seit 2005
vor 9 Jahren

Hallo Palladin007,

was hindert dich denn, per Reflection über den Typ zu laufen und zu ermitteln, welche Member er hat? Du könntest dann alle Member sortiert und mit ihren Typen bzw. Signaturen in einen String schreiben. Von dem String ermittelst du eine MD5-Summe und merkst du dir. Wenn du wissen willst, ob der Typ unverändert ist, ermittelst du die MD5-Summe wie beschrieben neu und vergleichst sie mit der alten.

herbivore

Palladin007 Themenstarter:in
2.079 Beiträge seit 2012
vor 9 Jahren

Ich habe jetzt doch einen Weg gefunden, der hoffentlich nicht zu langsam ist. Wirklich sehen, ob sich das lohnt, werde ich aber erst, wenn es wirklich eingebaut ist.

Im Prinzip mache ich nichts anderes, als mit ILSpy den Code zu dekompilieren und anschließend den Hashwert zu speichern:

public static string DecompileCSharpCode(Type type)
{
    var assemblyDefinition = AssemblyDefinition.ReadAssembly(type.Assembly.Location);

    var decompiler = new AstBuilder(new DecompilerContext(assemblyDefinition.MainModule));
    var typeDefinition = assemblyDefinition.MainModule.GetType(string.Concat(type.Namespace, ".", type.Name));
    decompiler.AddType(typeDefinition);

    using (var targetTextWriter = new StringWriter())
    {
        decompiler.GenerateCode(new PlainTextOutput(targetTextWriter));
        return targetTextWriter.ToString().Trim();
    }
}

So muss ich nicht einen komplett neuen Weg implementieren, wie ich das Interface eindeutig signieren kann und der Umfang hält sich stark in Grenzen. Nachteil ist, dass ich die ICSharpCode.Decompiler.dll (Von ILSpy) und Mono.Cecil.dll brauche.

Aber auf jeden Fall kann ich so den Hashwert mit abspeichern und immer abgleichen.

NuGet Packages im Code auslesen
lock Alternative für async/await

Beim CleanCode zählen nicht die Regeln, sondern dass wir uns mit diesen Regeln befassen, selbst wenn wir sie nicht befolgen - hoffentlich nach reiflichen Überlegungen.