2017-01-04 2 views
2

Ich arbeite mit Dynamics CRM (Was technisch für diese Diskussion irrelevant ist, erklärt aber einige der Hintergrundgeschichte zu diesem Thema). Es gibt zahlreiche Arten, die alle von der Klasse Entity abgeleitet sind. Ich möchte eine Class<T>() : where T: Entity erstellen, aber mit einer weiteren Einschränkung, dass es nur für bestimmte Klassen funktioniert, die von Entity abgeleitet sind.Wie am besten Typen in Generic <T> Klasse einzuschränken, wo alle von der gleichen Basisklasse abgeleitet sind

Meine aktuelle Methode, dies zu tun, ist eine enum Anpassung der Entitätsnamen ich verwenden möchte, haben, if/else if/else mich durch diesen Typen und throw, wenn ein ungültiger Typ übergeben wird.

Es fühlt sich ungeschickt, und ich fühle, dass ich wäre besser dran, etwas zu schreiben, wie,

public class ProductConverter<t> where T: Entity (OpportunityProduct, QuoteProduct, AccountProduct) { ... }

diese Weise wird der Typ-Motor sagen kann: „wir arbeiten an einer Basisklasse von Entity, und auch wir sind nur arbeiten diese abgeleiteten Arten von Unternehmen ".

Ich hoffe, das gibt genug Klarheit, um zu verstehen, was ich tue - mein Ziel ist, dass ich eine Engine erstellen will, die Konvertierung zwischen Entity Records, die erweitert werden können, ohne große Teile des Codes neu schreiben müssen (Effektiv, ein Mapping hinzufügen und Parameter eingeben). Ich bin sicher, es gibt bessere Möglichkeiten, dies zu tun, also zeigen Sie sie bitte, wenn Sie sie sehen :)

@ henk-holterman fragte, ob ich die Klassen ändern könnte. Dies ist nicht möglich, da es sich um generierte Klassendateien handelt, die als Schnittstelle zum Dynamics CRM-Webdienst verwendet werden.

edit Wie @jamiec erwähnt, sind die Klassen partial, so kann ich dies tun, indem eine Schnittstelle zu den spezifischen Klassen definieren, ich ändern möchten.

+1

Können Sie die Entitätsklassen ändern? Hinzufügen einer Schnittstelle? Warum gibt es keine Basisklasse "Produkt"? –

+0

Nein, sie sind automatisch als Schnittstellen zum System generiert, ich habe die Kontrolle darüber. Ich werde die Frage aktualisieren. –

+0

Verwenden Sie 'typeof', um den Klassentyp zu testen, dann können Sie eine switch-Anweisung verwenden und für jeden Typ abstrahieren. – bilpor

Antwort

4

Ihre automatisch generierten Klassen sind mit ziemlicher Sicherheit partial, was bedeutet, dass Sie eine separate Datei für jede sollte eine gemeinsame Schnittstelle Implementierung

public partial class QuoteProduct : IProduct 
{ // probably empty } 

Dann können Sie Ihre generische Art von Schnittstelle einschränken:

public class ProductConverter<T> where T: Entity, IProduct 
{ // your implementation } 
+0

Danke für Ihre Hilfe - wie Sie erwähnt haben, sind sie "partiell", so dass der Konverter perfekt mit einer Schnittstelle funktioniert. Diese Schnittstelle wird es mir auch ermöglichen, einige der anderen Konvertierungsanforderungen zu generalisieren, die ich mir überlegt habe, wie das am besten funktioniert, also funktioniert alles gut. –

+1

@PeterStreet cool, froh, ich könnte mit einem frivolen/Wegwerf-Kommentar helfen. Manchmal vermisst man den Wald für die Bäume;) – Jamiec

+0

[Rubber Duck Debugging] (https://en.wikipedia.org/wiki/Rubber_duck_debugging) mit Stack Overflow für die Ente;) –

0

Sie müssen eine Schnittstelle implementieren, die dann von jeder Klasse implementiert wird, die Sie verwenden möchten. Dies könnte zum Beispiel wie folgt aussehen:

public interface IProduct 
{ 
    int ProductId {get;set;} 
} 

public class ProductConverter<t> where T: Entity, IProduct 
{ 
    //Do sth. with your ProductId 
} 

Da Ihre Klassen generiert werden, wie Sie im Kommentar beschrieben, wird dies in Ihrem speziellen Fall nicht funktionieren. Dann haben Sie nur die Möglichkeit, die Typprüfung zu verwenden:

T obj; 
if (obj.GetType() == typeof(YourClass)) 

//OR 

if (obj is YourClass) 

Das Problem ist, wenn Sie etw. Tun. Wie Sie in Ihrer Frage erwarten, ist Ihre Variable nutzlos, weil Sie nicht wissen, um welchen Typ es sich handelt.

public void ProductConverter<t>(T obj) where T: Entity (OpportunityProduct, QuoteProduct) 
{ 
    obj. //What to do here?? It can hold Methods from both OpportunityProduct or QuoteProduct 
} 

In der Tat haben Sie die Möglichkeit, das Zeug zu verallgemeinern, das Sie brauchen oder typecheck. Wenn Sie wissen, was passieren kann, kann Ihnen das Stichwort dynamic helfen. In diesem Fall brauchen Sie den generischen Ansatz nicht.Zum Beispiel kann dies wie folgt aussehen:

public void ProductConverter(dynamic entity) 
{ 
    //Make sure the method exists. Or you will get an Exception. 
    //The compiler can't warn you about this 
    entity.SomeMethod1(); 
    entity.SomeMethod2(); 
} 

Nicht sicher, ob dies Ihnen wirklich helfen kann, wenn Sie einen Konverter schreiben möchten.

+0

Danke dafür. Ich habe nicht bemerkt, dass die generierten Klassen "partiell" waren, was es mir ermöglichen würde, meine eigenen Klassen auf diese ... anzuhängen. Dumm von mir, das nicht zu bemerken, aber ich war ein bisschen blind für das, was generiert wurde. Auf diese Weise kann ich die Konvertierungsmethoden direkt in jede Klasse implementieren, um die anderen Klassen zu generieren, ohne sich Gedanken über Kollisionen machen zu müssen. –

+1

@PeterStreet Nun, glücklich zu hören, dass Sie eine Lösung gefunden haben. – Sebi

+0

So bin ich, danke für deine Hilfe :) –

Verwandte Themen