Kann ich nicht zulassen, dass andere Assemblies von einer Klasse erben?

8

Ich habe so etwas:

%Vor%

Ich muss SomeDataBlob public angeben, damit es als Mitglied der öffentlichen Schnittstellenmethode ExternalPlugin.DoStuff verwendet werden kann. Ich möchte jedoch nicht zulassen, dass Clients von dieser Klasse erben und somit anfällig für das Problem der spröden Basisklasse sind. (Alle Derivate dieser Klasse sollten in derselben Baugruppe aufbewahrt werden)

Das Markieren der Klasse sealed geht zu weit, weil ich glaube, dass das Entfernen von sealed eine Änderung der API ist; Und selbst wenn dies nicht der Fall ist, können die SomeDataBlobV2 clients nach dem Versand immer noch das Falsche tun und direkt von SomeDataBlob erben.

Gibt es eine Möglichkeit, diese Art von Muster zu erzwingen?

    
Billy ONeal 02.07.2013, 20:40
quelle

6 Antworten

3
___ answer17435585 ___

Machen Sie die Klasse intern und geben Sie stattdessen eine Schnittstelle frei. Verwenden Sie dann das Factory-Muster, um die korrekte Implementierung zu erstellen.

%Vor%

Sie verbergen die Implementierung, aber geben dem Benutzer immer noch Zugriff auf alles. Sie machen sogar Komponententests für Ihre Benutzer einfacher;)

Bearbeiten (auf einen Kommentar des OP antworten)

  

Was ich effektiv möchte, ist eine Methode, die einige Parameter annimmt. Ich möchte in der Lage sein, Parameter hinzuzufügen, die die Hauptanwendung in einer zukünftigen Version bereitstellen kann, wenn die API ohne Clients zu brechen. Aber ich möchte nicht, dass Clients in der Lage sind, Instanzen der "Parameter" -Klasse / -Schnittstelle zu erstellen oder anderweitig mit ihr zu interagieren, anstatt eine Instanz davon als Parameter zu erhalten

Anstatt die APIs zu verstecken, können Sie sicherstellen, dass alle an Ihre Bibliothek übergebenen Objekte von Ihrer Assembly stammen:

%Vor%

Bearbeiten2

Habe gerade bemerkt, dass @RQDQ diese Lösung bereits bereitgestellt hat (habe es bei der Beantwortung Ihres Kommentars nicht bemerkt). Wenn das die Lösung ist, die Sie wollen, akzeptieren Sie stattdessen seine Antwort.

    
___ qstntxt ___

Ich habe so etwas:

%Vor%

Ich muss %code% public angeben, damit es als Mitglied der öffentlichen Schnittstellenmethode %code% verwendet werden kann. Ich möchte jedoch nicht zulassen, dass Clients von dieser Klasse erben und somit anfällig für das Problem der spröden Basisklasse sind. (Alle Derivate dieser Klasse sollten in derselben Baugruppe aufbewahrt werden)

Das Markieren der Klasse %code% geht zu weit, weil ich glaube, dass das Entfernen von %code% eine Änderung der API ist; Und selbst wenn dies nicht der Fall ist, können die %code% clients nach dem Versand immer noch das Falsche tun und direkt von %code% erben.

Gibt es eine Möglichkeit, diese Art von Muster zu erzwingen?

    
___ answer17435646 ___

Soweit ich weiß, sind Schnittstellen dafür der richtige Weg. Es wäre eine Änderung der API, aber es würde bedeuten, dass Sie tun könnten, was Sie wollen.

%Vor%

Und dann, damit die Objekte das Fabrikmuster verwenden, z. B.

%Vor%     
___ answer17439542 ___

SomeDataBlob kann nicht vererbt werden, da sein einziger Konstruktor intern ist. Wenn Sie versuchen, eine abgeleitete Klasse in einer Clientanwendung zu implementieren:

%Vor%

Sie erhalten den folgenden Fehler:

  

Der Typ 'ClassLibrary1.SomeDataBlob' hat keine Konstruktoren definiert

Es scheint, dass Sie Ihr eigenes Problem gelöst haben.

    
___ tag123c ___ C # (sprich "Cis") ist eine objektorientierte Programmiersprache auf hohem Niveau, die für die Erstellung einer Vielzahl von Anwendungen entwickelt wurde, die auf dem .NET Framework (oder .NET Core) ausgeführt werden. C # ist einfach, leistungsfähig, typsicher und objektorientiert. ___ answer17435718 ___

Was ich tun würde, ist eine Art Factory-Klasse zu erstellen, die eine Schnittstelle zur Verfügung stellt, die eine Instanz jeder Version für die spezifische API, die Ihr Client verwendet, übergibt und die Implementierung mit einer internen Klasse versteckt.

Sie können Constraints auch verwenden, um die Verwendung zu vereinfachen. Dann kann der Client einfach den Objekttyp eingeben, nach dem er sucht

%Vor%     
___ answer17435666 ___

Wenn Sie nicht versiegelt sind und keine Klassen verwenden, können Sie dies zur Laufzeit erzwingen. Überprüfen Sie an der API-Grenze die beteiligten Klassen und stellen Sie sicher, dass sie von Ihrer Assembly stammen.

Ein einfaches Beispiel:

%Vor%     
___ qstnhdr ___ Kann ich nicht zulassen, dass andere Assemblies von einer Klasse erben? ___
RenniePet 02.07.2013, 20:46
quelle
9

Machen Sie die Klasse intern und geben Sie stattdessen eine Schnittstelle frei. Verwenden Sie dann das Factory-Muster, um die korrekte Implementierung zu erstellen.

%Vor%

Sie verbergen die Implementierung, aber geben dem Benutzer immer noch Zugriff auf alles. Sie machen sogar Komponententests für Ihre Benutzer einfacher;)

Bearbeiten (auf einen Kommentar des OP antworten)

  

Was ich effektiv möchte, ist eine Methode, die einige Parameter annimmt. Ich möchte in der Lage sein, Parameter hinzuzufügen, die die Hauptanwendung in einer zukünftigen Version bereitstellen kann, wenn die API ohne Clients zu brechen. Aber ich möchte nicht, dass Clients in der Lage sind, Instanzen der "Parameter" -Klasse / -Schnittstelle zu erstellen oder anderweitig mit ihr zu interagieren, anstatt eine Instanz davon als Parameter zu erhalten

Anstatt die APIs zu verstecken, können Sie sicherstellen, dass alle an Ihre Bibliothek übergebenen Objekte von Ihrer Assembly stammen:

%Vor%

Bearbeiten2

Habe gerade bemerkt, dass @RQDQ diese Lösung bereits bereitgestellt hat (habe es bei der Beantwortung Ihres Kommentars nicht bemerkt). Wenn das die Lösung ist, die Sie wollen, akzeptieren Sie stattdessen seine Antwort.

    
jgauffin 02.07.2013 20:46
quelle
2

Wenn Sie nicht versiegelt sind und keine Klassen verwenden, können Sie dies zur Laufzeit erzwingen. Überprüfen Sie an der API-Grenze die beteiligten Klassen und stellen Sie sicher, dass sie von Ihrer Assembly stammen.

Ein einfaches Beispiel:

%Vor%     
RQDQ 02.07.2013 20:51
quelle
1

Soweit ich weiß, sind Schnittstellen dafür der richtige Weg. Es wäre eine Änderung der API, aber es würde bedeuten, dass Sie tun könnten, was Sie wollen.

%Vor%

Und dann, damit die Objekte das Fabrikmuster verwenden, z. B.

%Vor%     
It'sNotALie. 02.07.2013 20:50
quelle
0

Was ich tun würde, ist eine Art Factory-Klasse zu erstellen, die eine Schnittstelle zur Verfügung stellt, die eine Instanz jeder Version für die spezifische API, die Ihr Client verwendet, übergibt und die Implementierung mit einer internen Klasse versteckt.

Sie können Constraints auch verwenden, um die Verwendung zu vereinfachen. Dann kann der Client einfach den Objekttyp eingeben, nach dem er sucht

%Vor%     
konkked 02.07.2013 20:55
quelle
0

SomeDataBlob kann nicht vererbt werden, da sein einziger Konstruktor intern ist. Wenn Sie versuchen, eine abgeleitete Klasse in einer Clientanwendung zu implementieren:

%Vor%

Sie erhalten den folgenden Fehler:

  

Der Typ 'ClassLibrary1.SomeDataBlob' hat keine Konstruktoren definiert

Es scheint, dass Sie Ihr eigenes Problem gelöst haben.

    
fcuesta 03.07.2013 04:11
quelle

Tags und Links