Hallo, ich glaube mich auf dem Holzweg zubefinden und etwas Hilfe wäre
nicht verkehrt.
Kurz und knapp ist mein Verständnis der Interfaces in C#
"Interfaces sind ein Vertrag und alle Methoden müssen in der geerbten
Klasse implementiert sein."
In meinem Beispiel möchte ich gerne verschiedene Herstellermultimeter in
meiner Applikation über Intefaces nutzen. Der Hersteller bietet für die
verschiedenen Multimeter je nach Preisklasse mehr Funktionen wie mit
einem SimpleMultimeter und Complexmultimeter dargestellt. In dem Fall,
dass es in der Zukunft ein MegaComplexmultimeter gibt, könnte ich die
weiteren Funktionen des Gerätes über andere Interfaces nutzen, zumindest
wäre das mein Verständnis.
Ist das zu kompliziert gedacht und ich sollte mir lieber Gedanken um das
Protokoll und Hardwareinterface z.B. RS232/GPIB machen?
Kennt jemand für solch eine Problematik Bücher, Beispiele oder kann mich
in die richtige Richtung schubsen, insbesondere, wenn auch noch der
Hersteller variabel ist?
Moin,
so, wie du das hinschreibst, schreit es förmlich nach Komposition statt
Vererbung^^.
mach dich mal schlau drüber. Wenn du Fragen hast, stell sie hier.
Grüße,
Danke für den Hinweis, jetzt komme ich immer mehr ins trudeln.
Jetzt müsste ich nochmal mein SW Konzept überdenken, deshalb würde ich
kurz mein Konzept mit euch teilen.
Die MainApp (executable) bietet die GUI für den Endanwender. Der
Endanwender kann in dieser Applikationen Plugins/Addons laden. Die
Plugins sind Assemblies (DLL's), welche zur Laufzeit geladen werden in
Anhängigkeit, welche Pluginlizenzen er besitzt und die Plugins/Addins
sind z.b. für ein Multimeter. In der GUI besitzt der Endandwender
eigentlich nur ein Multimeter, welche die Basisfunktionen zur Verfügung
stellt und nahezu Typenunabhängig vom Hersteller funktioniert.
Wenn ich mir Beispiele für Interfaces anschaue findet man Beispiele für
einen Logger sehr oft.
Wenn ich nun das Beispiel auf meine Projektanwende, dann sollte meiner
Mainapplikation egalsein, welches Multimeter in dem Plugin angebunden
ist.
Hauptsache ich bekomme über das Interface die Werte und mit dem
Loggerbeispiel scheint es so zusein.
Mein Problem ist, dass neue Funktionen eines Multimeter immer zufolge
hat, dass ich mein Interface anfassen muss und es ist zeitintensiv. Gibt
es dafür ansonsten eine andere Möglichkeit?
Torben schrieb:> Mein Problem ist, dass neue Funktionen eines Multimeter immer zufolge> hat, dass ich mein Interface anfassen muss und es ist zeitintensiv. Gibt> es dafür ansonsten eine andere Möglichkeit?
bei C# kann man mit Reflexion die Methoden eines Objekts abfragen. Damit
könnte man ein dynamischen Interface machen.
Aber was hilft es, wenn man Messgerät eine neue Funktion hat, aber die
GUI damit nicht umgehen kann?
Hallo Torben,
Deine Grundgedanke ist schon soweit korrekt.
Du kannst relativ einfach prüfen, ob ein Messinstrument ein Interface
implementiert.
1
varmultimeter=newSimpleMultimeter();
2
varfrequenceMeter=multimeterasIFrequency;
3
if(frequenceMeter==null)// keine Frequenzmessung
4
{
5
}
Über solche Prüfungen kannst Du Deine GUI steuern und in Abhängigkeit
prüfen ob ein Multimeter bestimmte Funktionen implementiert.
In Deinen Interfacen solltest Du jeweils den maximal möglichen
Funktionsumfang einer Multimetertyps definieren. Dinge die ein
Multimeter nicht unterstützt, liefern einen Konstantenwert oder einen
Hinweis an der Oberfläche.
Gruß
Frank
@Peter II
>Aber was hilft es, wenn man Messgerät eine neue Funktion hat, aber die>GUI damit nicht umgehen kann?
Natürlich könnte der Designer der UI schon Labels für dynamischen Text
und Werte vorbereiten, aber das Databinding würde nicht funktionieren.
@Frank
Danke für die Bestätigung. Die Interfaces für die Maximalausstattung zu
definieren wird natürlich extrem schwer, weil niemand in die Zukunft
schauen kann.
Eine Frage würde ich gerne noch stellen. Das Beispiel wäre kein
neutrales Interface, oder doch?
Torben schrieb:> Danke für die Bestätigung. Die Interfaces für die Maximalausstattung zu> definieren wird natürlich extrem schwer, weil niemand in die Zukunft> schauen kann.
Du kannst das aber dynamischer gestalten. Deine Klasse fürs Multimeter
kann ja Informationen bereithalten, an denen sich dein UI entlang
hangeln kann und gesagt bekommt, was sie mit den Daten anfangen soll. Am
Ende des Tages ist es ja doch nur eine Zahl, die dargestellt werden
will.
Torben schrieb:> Eine Frage würde ich gerne noch stellen. Das Beispiel wäre kein> neutrales Interface, oder doch?> public interface Logger> {> public void Log(LogLevel level, string msg);> public void Log(LogLevel level, string msgType, string msg);> public void InitLogSession();> public void EndLogSession();> public void AddLogger(Logger chainedLogger);> public void RemoveLogger(Logger chainedLogger);> }
Das sieht für mich eher nach einer Klasse aus, die Vorgänge und Fehler
in einem Programm mitloggen soll. So was in der Art wie:
Netzwerkverbindung zu Remote Ziel aufgebaut". Also solcher Kram, der
immer kommt, wenn man die verbosity von kommandozeilen Tools aufdreht.
In meinen Augen ist das für die Schnittstelle zu einem Multimeter
ungeeignet.
Da würde ich eher so Sachen wie:
Hallo Torben,
die Frage ist nicht so einfach zu beantworten.
Interface allgemein dienen nur einem Zweck, verschleiere was dahinter
passiert.
Im Gegensatz zur Vererbung, könnten Objekte unterschiedlicher Art, die
ein gemeinsames Interface implementieren in einer Liste vom Type des
Interfaces gesammelt werden.
Ruft man dann eine Methode auf, die im Interface beschrieben ist, wird
jedes Objekt seine Implementierung der Methode ausführen.
Zu Deiner Frage, ja jede Klasse, die dieses Interface implementiert,
kann Daten loggen. Das können komplexe Dinge sein wie Log4Net oder Deine
eigenen Objekte wenn sie dieses Interface implementieren.
Und ja, Du hast Recht, es gibt keine Möglichkeit im voraus alle
Möglichkeiten zu bedenken. Du wirst irgendwann immer Deine GUI und Deine
Klassen anpassen müssen.
Um diesen Zeitpunkt aber soweit wie möglich heraus zuschieben, ist es
sinnvoll sich am maximalsten was heute geht zu orientieren und die
Interface daran zu orientieren.
Die Interface bringen dir aber die Sicherheit, dass wenn Du eine
Methodensignatur änderst oder eine Methode hinzufügst oder entfernst
alle Klassen, die dieses Interface implementieren bzw. deren
Abhängigkeiten beim Compilieren Fehler werfen. Du letztlich nur diese
Bereiche anpassen musst.
Schau Dir in diesen Zusammenhang auch mal MEF an. MEF würde Deinen
Gedanken einer Pluginstruktur optimal unterstützen.
Gruß
Frank
var multimeter = new SimpleMultimeter();
var frequenceMeter = multimeter as IFrequency;
if (frequenceMeter == null) // keine Frequenzmessung
{
}
das geht viel kürzer:
if (frequenceMeter is IFrequency)
Gruß J
jo schrieb:> var multimeter = new SimpleMultimeter();> var frequenceMeter = multimeter as IFrequency;> if (frequenceMeter == null) // keine Frequenzmessung> {> }>> das geht viel kürzer:>> if (frequenceMeter is IFrequency)
I.d.R. will man mit einem Objekt vom Typ IFrequency auch was anfangen.
Soll heißen, der "cast", den Frank außerhalb des ifs gemacht hat, musst
Du noch im if machen. Von den Anzahl der Code-Zeilen ist beides in
diesem Fall also gleichwertig. Davon abgesehen ist abr der as-Operator
etwas effizienter:
https://msdn.microsoft.com/de-de/library/cc488006.aspx
Grüße
Markus
@Torben:
Deine Ausgangsfrage lese ich in der Art: Wie verwende ich Interfaces?
Die wesentlich spannendere Frage ist aber: Warum verwende ich
Interfaces? Die einfache Antwort auf diese Frage lautet: Um statische
Abhängigkeiten von konkreten Implementierungen zu vermeiden.
Anders ausgedrückt: Durch Interfaces bist Du in der Lage verschiedene
Implementierungen (Multimeter-Modell-A und Multimeter-Modell-B) auf die
selbe Art und Weise über das abstrakte Interface zu verwenden (das beide
implementieren), ohne dass es Dich interessieren muss, welches
Multimeter-Modell denn nun konkret vorliegt.
Ein Interface zu definieren, ohne dass Objekte über dieses Interface
verwendet werden, ist ziemlich sinnfrei und verkompliziert Deinen Code
nur überflüssig.
Grüße
Markus
Hallo, soweit hatte ich die Interfaces auch verstanden, dass mir relativ
egal wie das Multimeter angesteuert wird. Ich benötige in meiner
Mainapplikation den PluginManager, GUI und Interfaces. Das Plugin muss
sich um die Anbindung der einzelnen Multimeter kümmern. Indem Fall finde
ich es nur doof, das jeder Pluginentwickler die Anbindung implementieren
muss, obwohl es sicherlich vorkommt, das die Anbindung, Protokolle etc.
für einige Multimeter identisch ist.
Ich bin noch etwas am überlegen, wie solche Fälle sinnvoll behandelt
werden damit es nicht verschiedene Plugins für namentlich
unterschiedliche Multimeter gibt, aber zur Ansteuerung identisch sind.
Torben schrieb:> Indem Fall finde> ich es nur doof, das jeder Pluginentwickler die Anbindung implementieren> muss, obwohl es sicherlich vorkommt, das die Anbindung, Protokolle etc.> für einige Multimeter identisch ist.
Sowas wird oftmals als generisches Gerät implementiert.
Hallo Torben,
grundsätzlich schreit das nach einer eigenen Kommunikationsklasse.
Messgeräte, die die gleiche Art der Kommunikation verwenden, werden über
die gleiche Klasse gehandelt.
Nochmal mein Tipp dazu beschäftige Dich mit MEF, hier findest Du alles
was Du benötigst, um möglichst viele Dinge wiederzuverwenden und
gleichzeitig modular zu bleiben.
Beschäftige Dich mal mit dem Thema "ImportingConstructor" innerhalb von
MEF
Gruß
Frank