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

  • »
  • Community
  • |
  • Diskussionsforum
Wie handhabt man reine Datencontainer, wenn es keine "friend" Klassen gibt?
Seikilos
myCSharp.de - Member



Dabei seit:
Beiträge: 759

Themenstarter:

Wie handhabt man reine Datencontainer, wenn es keine "friend" Klassen gibt?

beantworten | zitieren | melden

Hallo,

bei einem Projekt habe ich ein Austauschobjekt, welches Projekt heißt und so aussieht:


    public class Project
    {
        public string Path { get; set; }
        public bool Active { get; set; }
    }

Diese Objekte generiert die Logik und gibt sie nach Außen (GUI), welche diese dann anzeigt.
Weil die GUI diese Objekte vorhält und braucht, um Operationen in der Logik zu triggern, reicht die GUI bei Anfragen, wie z.B "Logic.SetProjectActiveStatus(Project, bool)" das Projekt und einen bool rein.
Die Methode selber führt dann so etwas aus wie:


project.Active = false;
// Weitere Statewechsel, File IO, etc

Nun bin ich selber wegen der Unzulänglichkeit dieses Ansatz auf die Nase gefallen.
Da der Datencontainer mutable ist, hab ich in einem Unit Test anstatt des Umwegs über Logic.SetProjectActiveStatus Active manuell auf false gesetzt, denn SetProjectActiveStatus hatte bis dato nur Active = false.
Jetzt aber, durch mehr Logik in der Logik schlagen recht viele der Tests fehlt.

Hier fehlt mir ein bisschen das friend Konzept aus C++.

Wie wird das generell gehandhabt? Ich will keine Logik in die Datencontainer, d.h das Property Active soll nicht mehr tun (kann es auch garnicht, der Kontext fehlt).
Den Container immutable zu machen gefällt mir auch nicht, weil ich jedes mal neue Project instanzen erzeugen muss, die dann zur GUI, etc wandern. Dadurch muss ich die Datenhaltung in der GUI ändern, weil die Projekte nicht mehr vergleichbar sind. Außerdem muss ich die Projekte wegen so etwas wie einem geänderten Active Flag klonen.

Was würde man da machen? Eine INotifyPropertyChanged Schnittstelle wäre denkbar, aber ich will ja nicht, dass GUI auf den Daten etwas macht.
Life is a short
private Nachricht | Beiträge des Benutzers
TheBrainiac
myCSharp.de - Member

Avatar #avatar-3152.png


Dabei seit:
Beiträge: 832
Herkunft: /dev/null

beantworten | zitieren | melden

Wie wäre es mit sowas (sehr verkürzte Form):

public interface IProject {
    string Path { get; }
    string Active { get; }
}

private class ConcreteProject : IProject {
    public string Path { get; set; }
    public string Active { get; set; }
}

public class Logic {
    public IProject CreateProject(string path) {
        return new ConcreteProject { Path = path; Active = false; };
    }
    public void SetProjectActiveStatus(IProject p, bool a) {
        ((ConcreteProject)p).Active = a;
    }
}

Gruß, Christian.
There are 10 types of people in the world:
Those, who think they understand the binary system
Those who don't even have heard about it
And those who understand "Every base is base 10"
private Nachricht | Beiträge des Benutzers
Seikilos
myCSharp.de - Member



Dabei seit:
Beiträge: 759

Themenstarter:

beantworten | zitieren | melden

Hallo,
ich bin bei der Lösung unschlüssig.
Der Contract hat dann nur die Getter, das ist ein Vorteil, aber alle Operationen auf der Logik erfordern dann das casten in die private Klasse.

Ist das der übliche Weg?
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Seikilos am .
Life is a short
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 Seikilos,

ich vermute mal, dass geschachtelte Klassen nicht in Frage kommen. Geschachtelte Klassen wären aus meiner Sicht am ehesten der Ersatz für Friends, denn Friends sollten m.E. eh nur Klassen sein, die in sehr enger Beziehung stehen, also insbesondere in der gleichen Assembly definiert sind. Dann kann man sie aber eben auch gleich schachteln.
Zitat
aber alle Operationen auf der Logik erfordern dann das casten in die private Klasse.
Den Einwand verstehe ich nicht. Im GUI verwendest du die Schnittstelle; das GUI kennt die Klasse gar nicht. In der Logik verwendest du die Klasse und die Schnittstelle interessiert dich nicht. Was spricht bei dir dagegen?

herbivore
private Nachricht | Beiträge des Benutzers
Seikilos
myCSharp.de - Member



Dabei seit:
Beiträge: 759

Themenstarter:

beantworten | zitieren | melden

Wenn es das übliche Vorgehen ist, stelle ich mich dem nicht entgegen, ich finde nur das casten in jeder einzelnen Methode der Logik etwas mühsam.

Bei der GUI stimme ich dem zu, dass ist elegant gelöst.
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Seikilos am .
Life is a short
private Nachricht | Beiträge des Benutzers
Sarc
myCSharp.de - Member



Dabei seit:
Beiträge: 426

beantworten | zitieren | melden

Hallo,

reicht die internal Sichtbarkeit für dich evtl. aus?
Dann könntest du die setter internal machen und sie sind somit nur von deiner Logik Klasse setzbar, da sich diese in der gleichen Assembly befindet (ich nehme an, die GUI ist in einer separaten Assembly).
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 Seikilos,

wenn du es so machst, wie ich geschrieben habe, musst du nicht casten, zumindest nicht dauernd.

herbivore
private Nachricht | Beiträge des Benutzers
Seikilos
myCSharp.de - Member



Dabei seit:
Beiträge: 759

Themenstarter:

beantworten | zitieren | melden

Internal finde ich gut. Das könnte es sein.
Zitat
Im GUI verwendest du die Schnittstelle; das GUI kennt die Klasse gar nicht. In der Logik verwendest du die Klasse und die Schnittstelle interessiert dich nicht. Was spricht bei dir dagegen?
Wenn das Interface IProject ist und die GUI übergibt immer das IProject an die Logik, so muss bei jeder Übergabe an die Logik das IProject in ein Project gecastet werden, damit Setter benutzt werden können.
Jede Logik Methode, die ein IProject bekommt, muss daher casten.
Life is a short
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 Seikilos,
Zitat
GUI übergibt immer das IProject an die Logik, so muss bei jeder Übergabe an die Logik das IProject in ein Project gecastet werden, damit Setter benutzt werden können.
das ist offensichtlich kein guter Weg, denn das GUI könnte auch ein Objekt jeder anderen Klasse übergeben, die IProject implementiert, und dann würde es knallen.

In so einer Konstellation dann doch lieber direkt die Klasse und kein Interface benutzen und stattdessen internal verwenden, damit die die Logik auf Projekt zugreifen kann, wenn sich diese eh in einer Assembly befinden.

herbivore
private Nachricht | Beiträge des Benutzers
FZelle
myCSharp.de - Experte



Dabei seit:
Beiträge: 10083

beantworten | zitieren | melden

Wenn man MVVM oder MVP ( Passiv View ) einsetzt, muss man sich über so etwas keine Gedanken machen, da hier das View nichts an die Logik übergibt.
Das ist auch der Grund warum man so etwas benutzen sollte.
private Nachricht | Beiträge des Benutzers