Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

Typen nach ihrem Aufbau vergleichen (um festzustellen, ob sich die Definition des Typs geändert hat)
Palladin007
myCSharp.de - Member

Avatar #avatar-4140.png


Dabei seit:
Beiträge: 1516
Herkunft: Düsseldorf

Themenstarter:

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

beantworten | zitieren | melden

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ß
private Nachricht | Beiträge des Benutzers
unconnected
myCSharp.de - Member

Avatar #avatar-3200.jpg


Dabei seit:
Beiträge: 862
Herkunft: Oerlinghausen/NRW

beantworten | zitieren | melden

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?
private Nachricht | Beiträge des Benutzers
Palladin007
myCSharp.de - Member

Avatar #avatar-4140.png


Dabei seit:
Beiträge: 1516
Herkunft: Düsseldorf

Themenstarter:

beantworten | zitieren | melden

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.
private Nachricht | Beiträge des Benutzers
Spyke
myCSharp.de - Member



Dabei seit:
Beiträge: 146

beantworten | zitieren | melden

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)
Dieser Beitrag wurde 2 mal editiert, zum letzten Mal von Spyke am .
private Nachricht | Beiträge des Benutzers
Palladin007
myCSharp.de - Member

Avatar #avatar-4140.png


Dabei seit:
Beiträge: 1516
Herkunft: Düsseldorf

Themenstarter:

beantworten | zitieren | melden

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.
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 52329
Herkunft: Berlin

beantworten | zitieren | melden

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
private Nachricht | Beiträge des Benutzers
Palladin007
myCSharp.de - Member

Avatar #avatar-4140.png


Dabei seit:
Beiträge: 1516
Herkunft: Düsseldorf

Themenstarter:

beantworten | zitieren | melden

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.
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Palladin007 am .
private Nachricht | Beiträge des Benutzers