Laden...

Interfaces mit Möglichkeiten zur Prüfung auf validen Zustand des Objekts

Erstellt von Christoph K. vor 12 Jahren Letzter Beitrag vor 12 Jahren 4.775 Views
Thema geschlossen
Christoph K. Themenstarter:in
821 Beiträge seit 2009
vor 12 Jahren
Interfaces mit Möglichkeiten zur Prüfung auf validen Zustand des Objekts

Hallo Leute,

ich habe einen Satz von Interfaces und einen Satz von Objekten. Die Objekte können nach belieben die angebotenen Interfaces implementieren.
Nun kann es jedoch vorkommen, dass ein Objekt sich in einem Status befindet, wo es der Implementierung des Interfaces nicht genüge tut. Unter "nicht genüge tut" verstehe ich, dass z.B. wichtige Eigenschaften des Interfaces noch auf NULL stehen oder der Zustand der zu den des Interface zugehörigen Daten invalid ist.

Ich habe mir nun überlegt, jedem Interface eine Methode zur Statusüberprüfung mitzugeben, z.B. GetCurrentState() oder sowas in der Richtung. Hierüber könnte man dann prüfen, in wie weit, das Objekt diesem Interface genüge tut.

Die große Frage vor der ich nun Stelle ist: Wie generalisiere ich das ganze?
Ich kann ja schließlich kein Basisinterface erstellen, da die Methode ja pro Interface andere Werte liefern soll.

Jemand Ideen?

731 Beiträge seit 2006
vor 12 Jahren

Hi,

also vorweg... wenn eine Klasse ein Interface implementiert, dann implementiert eine Instanz dieser Klasse das Interface zu genüge. 😃

Kannst du deine Abfrage auf Gültigkeit nicht allgemeiner halten? Z.B. eine Methode "IsValid() --> {true, false} einführen? Die könntest du dann ja in einem "Basisinterface" verankern.

MfG
wax

Christoph K. Themenstarter:in
821 Beiträge seit 2009
vor 12 Jahren

Das Problem ist, das wenn ich die Funktion in einem Basisinterface veranker, ja immer nur geprüft werden kann Basisinterface.IsValid() und nicht ob die Schnittstellen die das BAsisinterface implementieren valide sind.

49.485 Beiträge seit 2005
vor 12 Jahren

Hallo Christoph K.,

ich sehe das wie Wax. Das Interfaces wird von der Klasse implementiert und da und nur da, muss es korrekt implementiert sein. Wenn es das ist, "implementiert" jedes Objekt das Interfaces korrekt. Es kann also nur darum gehen zu prüfen, ob sich das Objekt in einem validen Zustand befindet. Den Titel habe ich entsprechend angepasst.

Und natürlich kannst du eine Methode oder Property aufnehmen, mit der man prüfen kann, ob das Objekt valide ist. Im einfachsten Fall einfach eine Property IsValid. Diese kann es in jedem Interface geben. Wenn eine Klasse mehrere Interfaces implementiert, muss sie die Property entsprechend oft interface-explizit definieren. Beim Zugriff über das jeweilige Interface wird dann automatisch die richtige Property verwendet.

herbivore

Christoph K. Themenstarter:in
821 Beiträge seit 2009
vor 12 Jahren

Hi herbivore,

das was du wahrscheinlich meinst ist die explizite Implementierung von Interfaces.
Ich muss jedoch generell prüfen, ob ein Objekt ein Interface implementiert. Hierbei kenne ich nur den Basistyp des Objektes und den Basistyp des Interfaces. Das Interface selbst ist nicht bekannt.
Somit kann ich ja letztendlich nur das Basisinterface daraufhin prüfen ob es valide ist, da ich ja immer nur die Implementierung für das Basisinterfaces ansprechen kann.

C
1.214 Beiträge seit 2006
vor 12 Jahren

Die große Frage vor der ich nun Stelle ist: Wie generalisiere ich das ganze?
Ich kann ja schließlich kein Basisinterface erstellen, da die Methode ja pro Interface andere Werte liefern soll.

Warum? Du willst doch nur wissen, ob das Objekt valide ist. Das ist ein true oder false. Also sowas:


interface IValidatable
{
    bool IsValid();
}

interface MyInterface1: IValidatable
{
...
}

C
1.214 Beiträge seit 2006
vor 12 Jahren

Ich muss jedoch generell prüfen, ob ein Objekt ein Interface implementiert.

Ich finde deine Ausdrucksweise verwirrend. Ein Objekt implementiert das Interface, oder nicht. Das kannst du mit "is" überprüfen.
Ob sich das Objekt gerade in einem gültigen Zustand befindet, ist eine andere Frage. Ich finds auch generell nicht sehr sauber zu sagen, ein Objekt implementiert Interface1, Interface2, Interface3, und dabei ist grad nur Interface2 verwendbar.

I
279 Beiträge seit 2008
vor 12 Jahren

Ich muss jedoch generell prüfen, ob ein Objekt ein Interface implementiert. Hierbei kenne ich nur den Basistyp des Objektes und den Basistyp des Interfaces. Das Interface selbst ist nicht bekannt.

Wie willst du prüfen ob ein Typ ein bestimmtes Interface implementiert wenn du nur den Basistyp kennst? Du kannst ja von dem Basistyp nicht auf den abgeleiteten Typ schließen ohne diesen nicht zu kennen.

Imho lässt sich dein Vorhaben nur mit Reflection lösen.
um zu sehen ob ein typ ein Interface implementiert kannst du "IsAssignableFrom" (prüft ob der typ in den angebenen konvertiert werden kan) oder "GetInterfaces" verwenden.

Christoph K. Themenstarter:in
821 Beiträge seit 2009
vor 12 Jahren

Gucke dir mal folgendes an:


interface IValidatable
{
    bool IsValid();
}

interface MyInterface1: IValidatable
{
...
}

interface MyInterface2: IValidatable
{
...
}

class MyClass: MyInterface1, MyInterface2
{
...
}


Wie prüfe ich nun ob IF1 bzw. IF2 valide ist?

Christoph K. Themenstarter:in
821 Beiträge seit 2009
vor 12 Jahren

Ich muss jedoch generell prüfen, ob ein Objekt ein Interface implementiert. Hierbei kenne ich nur den Basistyp des Objektes und den Basistyp des Interfaces. Das Interface selbst ist nicht bekannt.

Wie willst du prüfen ob ein Typ ein bestimmtes Interface implementiert wenn du nur den Basistyp kennst? Du kannst ja von dem Basistyp nicht auf den abgeleiteten Typ schließen ohne diesen nicht zu kennen.

Imho lässt sich dein Vorhaben nur mit Reflection lösen.
um zu sehen ob ein typ ein Interface implementiert kannst du "IsAssignableFrom" (prüft ob der typ in den angebenen konvertiert werden kan) oder "GetInterfaces" verwenden.

Genau mit Reflektion habe ich das ganze auch schon lösen können. Ich dachte nur es geht irgendwie anders.

731 Beiträge seit 2006
vor 12 Jahren

Ist es nicht so, dass du (je nach verwendetem Bereich) genau weisst welches Interface in Frage kommt? Wenn ja, dann kannst du ja versuchen das Objekt in diesen "Interface-Typ" zu casten und anschließend darauf "IsValid" aufrufen.

Wobei ein DownCast natürlich nicht so schön ist, wie wenn es sich durch ein anderes Objektmodel rein durch Polymorphismus lösen lassen würde.

MfG
wax

49.485 Beiträge seit 2005
vor 12 Jahren

Hallo Christoph K.,

jetzt muss ich doch noch mal nachfragen: Geht es darum, dass du ein Objekt von unbekanntem (dynamischen) Typ T in einer Variable vom (statischen) Typ IValidatable hast und nun wissen willst, welches Interfaces das Objekt implementiert, also dass du also genaugenommen wissen willst, ob ein bestimmtes Interface von der Klasse T implementiert wird. Wenn ja, ginge das mit is.

Oder geht es darum, dass das Objekt (genaugenommen dessen Klasse) zwar alle Interfaces implementiert, aber man prüfen möchte, ob das Objekt aufgrund seines (momentanen) Zustands valide ist oder nicht? Das ginge mit der IsValid-Property, die man im Zweifel auch nacheinander für alle Interfaces einzeln abfragen könnte.

Solange nicht klar ist, ob du das eine oder andere meinst, werden wir weiter munter aneinander vorbeireden.

herbivore

2.187 Beiträge seit 2005
vor 12 Jahren

Hallo @All,

Nur für die Vollständigkeit:
Microsoft hat so ein Interface schon im .Net Framework integriert IDataErrorInfo

Gruß
Juy Juka

Christoph K. Themenstarter:in
821 Beiträge seit 2009
vor 12 Jahren

@herbivore

Oder geht es darum, dass das Objekt (genaugenommen dessen Klasse) zwar alle Interfaces implementiert, aber man prüfen möchte, ob das Objekt aufgrund seines (momentanen) Zustands valide ist oder nicht? Das ginge mit der IsValid-Property, die man im Zweifel auch nacheinander für alle Interfaces einzeln abfragen könnte.

Genau darum geht es letztendlich.
Wenn ich jedoch folgendes für alle Interfaes mache, die von einem Typ IValidatable abgeleitet sind

PSEUDOCODE:
foreach IValidatable item of GetInterfaces(MyObject)
{
   isValid = item.IsValid()
}

wird ja immer nur die Methode IValidatable.IsValid() aufgerufen. Ich möchte jedoch für jedes Interface einzel prüfen ob dieses Interface valide ist. Eine unschöne Möglichkeit wäre z.B. in der Iteration über den genauen Interfacetyp eine per Konvention benannte Methode zu reflektieren und auszufüren.

49.485 Beiträge seit 2005
vor 12 Jahren

Hallo Christoph K.,

musst du denn am Ende wissen, bezüglich welcher Interfaces das Objekt invalid ist? Oder reicht dir eine pauschale Aussage für das Objekt als ganzes? Wenn letzteres, dann kannst du doch IValidatable.IsValid in allen Klassen so implementieren, dass es den richtigen Wert zurückgibt. Im Grunde brächtest du die ganzen einzelnen Interfaces gar nicht, wenn die gegenüber IValidatable keine weiteren Member hinzufügen.

Evtl. ist [Artikel] Attribute zur Prüfung von Properties verwenden was für dich.

herbivore

656 Beiträge seit 2008
vor 12 Jahren

Kann es sein, dass du sowas meinst?

interface ICanSave
{
   bool CanSave { get; }
   void Save();
}
interface ICanDelete
{
    bool CanDelete { get; }
    void Delete();
}
class CanDoBoth : ICanSave, ICanDelete
{
   //...
}

Auf einer Instanz der Klasse ist es jetzt möglich, dass aufgrund des Status CanDelete auf true wäre (und du damit Delete aufrufen darfst), aber CanSave auf false ist (und damit kein Save möglich wäre).

...nur, dass es bei dir so aussieht:

interface IValidatable
{
   bool IsValid { get; }
   void DoStuff();
}
interface IOther1 : IValidatable { }
interface IOther2 : IValidatable { }
class CanDoBoth : IOther1, IOther2
{
   //...
}

...und dein IsValid/DoStuff sich je nach angesprochenem Interface anders verhält (indems einmal Other1 und einmal Other2 macht).

Oder?

Christoph K. Themenstarter:in
821 Beiträge seit 2009
vor 12 Jahren

@BhaaL:
Dein zweites Beispiel ist genau das was ich meine. Die Implementierung von IsValid bzw. DoStuff wird jedoch die gleiche sein bezogen auf die Instanz von CanDoBoth.

656 Beiträge seit 2008
vor 12 Jahren

Warum machts dann einen Unterschied? Es ist für beide Interfaces dieselbe Methode; was heißt dass es gemäß dem Contract des Interface dasselbe tun sollte.

Wenn dem nicht so ist, solltest du vielleicht überlegen die Interfaces anders aufzuteilen.

...oder hat das Beispiel eigentlich gar nix mit deiner ursprünglichen Frage zu tun, sieht aber bei dir zufällig auch so aus?

Christoph K. Themenstarter:in
821 Beiträge seit 2009
vor 12 Jahren

Ok noch einmal ein abschließendes Beispiel. Nehmen wir an, ich habe folgenden Code.

public interface BaseInterface
{
	
}

public interface Interface1 : BaseInterface
{
	SomeStuff();
	
	bool IsInterfaceImplementationValid();
}


public interface Interface2 : BaseInterface
{
	SomeOtherStuff();
	
	bool IsInterfaceImplementationValid();
}

Wie ihr seht haben Interface1 und Interface2 jeweils eine Methode um die Validität des Interfaces zu testen. Auch wenn eine Klasse beide Interfaces implementiert ist es über die explizite Implementierung möglich, jeweils für IF1 und IF2 zu prüfen ob es valide ist.

Nun zu meinem Problem:

Ich möchte die Prüfung ob eine Interface valide ist generalisieren! Ich kenne bei der Prüfung nur die Klasse, die beliebig viele (validierbare) Interfaces implementiert und möchte für jedes dieser Interface explizit prüfen, ob es valide ist.

Mein erster Ansatz war, die Interfaces von einem BasisInterface ableiten zu lassen und dort eine Methode zu verlangen, die die Validität prüft. Dies führt jedoch dazu, dass bei der Prüfung verschiedener abgeleiteter Interfaces nicht mehr unterschiedlicher Code ausgeführt wird.

Ein Ansatz der Funktioniert (für mich jedoch ungenügend ist) ist, durch Reflektion alle Interfaces einer Klasse zu ermitteln und per Namenskonvetion den Menber zur Validierung zu ermitteln und aufzurufen.

C
1.214 Beiträge seit 2006
vor 12 Jahren

Ok, ich glaub jetzt die Problematik zu verstehen... Aber wenn es so ist wie in dem Beispiel von Bhaal, dann ist die Validierung ja Contextabhängig. Ist es bei dir nicht so? Sein Beispiel kann ich gut nachvollziehen, wüsste aber nicht, warum ich an der Stelle verallgemeinern und alle Interfaces abfragen sollte. Kannst du ein ähnliches Beispiel machen, dass deinem Problem ähnlich ist?

S
417 Beiträge seit 2008
vor 12 Jahren

Hallo,

Ich möchte die Prüfung ob eine Interface valide ist generalisieren!

Eigentlich möchtest Du doch die Implementierung prüfen, denn ein Interface an sich ist ja immer "valide".
Wieso reicht also nicht ein Interface mit einer Methode bool IsValid(), in der geprüft wird, ob alle implementierten Interfaces "valide" sind?

Christoph K. Themenstarter:in
821 Beiträge seit 2009
vor 12 Jahren

Es geht ja nicht darum zu prüfen ob das Objekt im allgemeinen valide ist, sondern darum, ob die Implementierung des Interfaces valide ist.

Das Objekt was Interface1, Interface2 und Interface3 implementiert kann somit z.B. im gegenwärtigen Zustand der Implementierung von Interface1 und Interface2 genügen, jedoch nicht der von Interface3.

Ein Objekt ist somit nicht insgesamt valide bzw. invalide sonder kann immer nur bezüglich einer Implementierung valide sein.

Christoph K. Themenstarter:in
821 Beiträge seit 2009
vor 12 Jahren

Hallo,

Ich möchte die Prüfung ob eine Interface valide ist generalisieren!
Eigentlich möchtest Du doch die Implementierung prüfen, denn ein Interface an sich ist ja immer "valide".
Wieso reicht also nicht ein Interface mit einer Methode bool IsValid(), in der geprüft wird, ob alle implementierten Interfaces "valide" sind?

Weil genau interessiert, im Bezug auf welches Interface das Objekt valide ist, bzw. nicht. (siehe hierzu auch meinen vorherigen Post).

C
1.214 Beiträge seit 2006
vor 12 Jahren

Nochmal, zumindest im Beispiel von Bhaal ist es Context abhängig. Also, in etwa so:


IDeletable del = obj as IDeletable;
if (del != null)
{
    if (del.CanDelete())
        del.Delete();
}

Und an einer anderen Stelle dann z.B.


ISaveable save = obj as ISaveable;
if (save!= null)
{
    if (save.CanSave())
        save.Save();
}

Warum möchtest du das jetzt verallgemeinern? Das Objekt muss ja nicht gleichzeitg löschbar und speicherbar sein. Beschreib deine Ausgangslage bitte genauer.

N
60 Beiträge seit 2010
vor 12 Jahren

Du könntest im Basis-Interface eine Funktion anbieten die als Rückgabewert ein Dictionary<Type, Boolean> hat.

In etwa so:


    public interface IBaseInterface {
        Dictionary<Type, Boolean> WhichInterfacesAreValid();
    }

    public interface IInterface1 : IBaseInterface {
        void SomeStuff();

        Boolean IsInterfaceImplementationValid();
    }

    public interface IInterface2 : IBaseInterface {
        void SomeOtherStuff();

        Boolean IsInterfaceImplementationValid();
    }

    public class Example : IInterface1, IInterface2 {
        public void SomeStuff() {
            throw new NotImplementedException();
        }

        public void SomeOtherStuff() {
            throw new NotImplementedException();
        }

        Boolean IInterface1.IsInterfaceImplementationValid() {
            return true;
        }

        Boolean IInterface2.IsInterfaceImplementationValid() {
            return true;
        }

        public Dictionary<Type, Boolean> WhichInterfacesAreValid() {
            var validationValues = new Dictionary<Type, Boolean>();

            validationValues.Add(typeof(IInterface1), ((IInterface1)this).IsInterfaceImplementationValid());
            validationValues.Add(typeof(IInterface2), ((IInterface2)this).IsInterfaceImplementationValid());

            return validationValues;
        }

    }

Das würde meiner Meinung nach Funktionieren, ob du nicht vielleicht doch eher dein Design überdenken musst kann ich nicht sagen und musst du wissen...

Grüße
Nils

Hinweis von herbivore vor 12 Jahren

Der Thread dreht sich schon seit längerem im Kreis.

Davon abgesehen sollte der Thread eigentlich genug Hinweise enthalten, die zu einer Lösung führen.

Thema geschlossen