Laden...
S
Stone1984 myCSharp.de - Member
Firmware Entwickler Dabei seit 19.11.2020 7 Beiträge
Benutzerbeschreibung

Forenbeiträge von Stone1984 Ingesamt 7 Beiträge

01.12.2020 - 22:11 Uhr

Vielen Dank Abt für den Hinweis. Dadurch habe ich jetzt die Lösung gefunden. Und habe das Interface


interface IA<E>
{
    ObservableCollection<E> data { get; set; }
}

erstellt und für die Klasse A bereitgestellt


class A<E>: IA<E>
{
....

und mit der Klasse B bekannt gemacht.


class B<T, E>: A<E> where T: IA<E>, new()
{
....

Damit läuft es jetzt so wie es soll.

Dass das kopieren wenig Sinn macht, das weiß ich. Ich habe nur nach einem vereinfachten Beispiel für mein Problem gesucht, denn der Code den ich sonst hätte wäre viel zu lang.

Den Punkt mit der Benennung muss ich mir mal genauer anschauen und dann das nächste Mal verwenden. Auf jeden Fall vielen Dank für die nützliche Antwort.

01.12.2020 - 21:45 Uhr

Guten Abend,

heute habe ich mal wieder ein Spezialproblem. Es geht um Generics und ich poste hier mal vereinfachten, beispielhaften code. Mein Hauptprogramm ist:


C test = new C();
test.data.Add(new Element() { ID = 0, NAME = "Test1" });
test.data.Add(new Element() { ID = 1, NAME = "Test2" });

C kopie = new C();
kopie = test.copy();

Hier lege ich so zu sagen das objekt Test von der Klasse C an und weiße ein paar Werte zu. Daraufhin lege ich Kopie an und lasse mir eine kopie von test ausgeben. Es soll nur das Prinzip meines Problems darstellen.

Die Klasse C sieht folgendermaßen aus:


class C:B<C, Element>
{
    public C()
    {

    }
}

public class Element
{
    public int ID { get; set; }
    public string NAME { get; set; }
}

C ist beispielsweise für eine Liste gedacht und Erbt von B, welche die Templateargumente C und Element übergeben bekommt.

Element stellt einfach ein Listenelement dar. C soll die unterste Ebene einer Liste darstellen. Es kann beispielsweise eine Liste für Autos sein, eine für Fahrräder usw.. Jede der Listen besitzt gleiche Funktionalitäten, die jedoch in der Elternklasse B algemein als Template Funktionen hinterlegt sind.

Dann kommen wir zur Klasse B:


class B<T, E>: A<E> where T: new()
{
    public B()
    {

    }

    public T copy()
    {
        T temp = new T();
        foreach (E element in data)
        {
            temp.data.Add(element);
        }
        return temp;
    }
}

In dieser Klasse wird die Kopie der aktuellen Liste angefertigt und zurückgegeben (ich weiß das macht keinen Sinn, aber soll nur prinzipiell mein Problem beschreiben). Hier tritt das nächste Problem auf. data ist nicht bekannt, obwohl es sich in der Basisklasse A von der Klasse B befindet. Es wird die Fehlermeldung:

Fehlermeldung:
Fehler CS1061 "T" enthält keine Definition für "data", und es konnte keine zugängliche data-Erweiterungsmethode gefunden werden, die ein erstes Argument vom Typ "T" akzeptiert (möglicherweise fehlt eine using-Direktive oder ein Assemblyverweis).

ausgegeben.

Die Basisklasse hat die folgende Form:

    
class A<E>
{
    public A()
    {
        data = new ObservableCollection<E>();
    }

     public ObservableCollection<E> data { get; set; }
}

In der Basisklasse ist data public und es ist ein get und set möglich. Durch die ObservableCollection muss auch das Add() möglich sein. Mir ist derzeit unklar wie ich diesen Fehler, das data nicht erkannt wird beheben kann. Hat an diesem Punkt jemand eine Idee?

Vielen Dank schon mal im Voraus.

26.11.2020 - 23:03 Uhr

@Papst: Vielen Dank für den Hinweis mit dem where. Nachdem ich die Zeile


class MySQLDataList<TList> where TList : IListInterface<TList>

in MySQLDataList ergänzt hatte läuft es einwandfrei und eröffnet neue Möglichkeiten.

Bin übrigends hauptsächlich aus der hardwarenahen C++ Welt. Bastelle aber nebenbei auch mit PHP, SQL und C# an Anwendungen herum.

26.11.2020 - 22:45 Uhr

Vielen Dank für den Hinweis. Das bedeutet, das ich zur Klasse CompanyList folgenden Code hinzufügen muss:


interface IListInterface<TList>
{
    void update(TList a_companyList);
}

class CompanyList : IListInterface<CompanyList>
{
......

Nur wie mache ich es dann in der Klasse MySQLDataList? Auf dieser Seite funktioniert es bei mir noch nicht.

26.11.2020 - 22:07 Uhr

Vielen Dank für die vielen nützlichen Hinweise und Tipps. Inwieweit das Synology NAS C# unterstützt weiß ich leider nicht. Um auf dieser Seite keine neue Baustelle zu eröffnen, werde ich vorerst erst einmal bei PHP bleiben.

Bezüglich der Datenübermittlung werde ich das ähnlich machen wie bisher und die Daten im Arbeitsspeicher als Listen vorhalten. Diese Observable Listen können sich dann wunderbar mit den WPF Steuerelementen wie z.B. das Gridview Element synchronisieren. Das hat auch bei den ersten Tests schon ganz gut funktioniert.

26.11.2020 - 22:02 Uhr

Guten Abend,

seit einigen Stunden bin ich schon dabei eine Lösung für einen Funktionsaufruf von einem Template (Generic) objekt ausgehend. Leider bekomme ich dabei den Fehler:

"TList enthält keine Funktion update"

Der zugrundeliegende Code sieht folgendermaßen aus:
Das Hauptprogramm ist:


MySQLDataList<CompanyList> companies = new MySQLDataList<CompanyList>();
companies.createEmptyObject();
companies.getDataList().data.Add(new Company { ID = 1, NAME = "Firma 1" });
companies.getDataList().data.Add(new Company { ID = 2, NAME = "Firma 2" });
companies.getDataList().data.Add(new Company { ID = 3, NAME = "Firma 3" });
companies.getDataList().data.Add(new Company { ID = 4, NAME = "Firma 4" });
CompanyList companyList = companies.getDataList();

CompanyList tempCompany = new CompanyList();
tempCompany.data.Add(new Company { ID = 2, NAME = "Firma 5" });
companies.update(tempCompany);

und die Klasse CompanyList ist:


class CompanyList
{
    public CompanyList()
    {
        data = new List<Company>();
    }

    public List<Company> data { get; set; }

    public void update(CompanyList a_companyList)
    {
        for (int i = 0; i < a_companyList.data.Count; i++)
        {
            update(a_companyList.data[i]);
        }
    }

    /**
     * \brief       Update eines Datensatzes.
     * \param[in]   Datensatz der geupdated werden soll.
     */
    public void update(Company a_company)
    {
        for (int i = 0; i < data.Count; i++)
        {
            if (data[i].ID == a_company.ID)
            {
                data[i].NAME = a_company.NAME;
            }
        }
    }
}

public class Company
{
    public int ID { get; set; }
    public string NAME { get; set; }
}

und schließlich die Klasse MySQLDataList:


class MySQLDataList<TList>
{
    public MySQLDataList()
    {
            
    }

    public void update(TList a_dataList)
    {
        m_dataList.update(a_dataList);
    }

    public void createEmptyObject()
    {
        m_dataList = new JavaScriptSerializer().Deserialize<TList>("{\"data\":[]}");
    }

    public TList getDataList()
    {
        return m_dataList;
    }

    TList m_dataList = default(TList);          //!< Liste mit Daten aus der Datenbank.
}

Probleme macht mir in dieser Klasse der Aufruf:


m_dataList.update(a_dataList);

Ich bin davon ausgegangen, da sich m_dataList in diesem Template vom Typ CompanyList ist und CompanyList die Funktion update besitzt, dass dieser Aufruf möglich wäre. Für mein TList ist sichergestellt, das jede Klasse, die für TList übergeben wird eine update-Methode enthält.

Kennt jemand eine Möglichkeit, wie ich in dem vorliegenden Programm einen gültigen Aufruf von update, ausgehend vom Objekt TList erzeugen kann? Gibt es evtl. in C# anderweitige Methoden, mit denen ich derartige generische Aufrufe realisieren kann?

Bei meiner Such bin ich bisher leider auf nichts vergleichbares gestoßen.

19.11.2020 - 22:17 Uhr

verwendetes Datenbanksystem: MySQL with MariaDB

Seit einiger Zeit versuche ich schon ein kleines Problem zu lösen. Ich möchte auf eine MySQL-Datenbank, die sich auf einem Webserver befindet zugreifen. Leider gibt es hier keine direkte Verbindung.

Bisher habe ich dafür C# Form Anwendungen genutzt, die Daten aus der Datenbank über ein serverseitiges PHP-Skript abholen können. Die Datenabfragen werden im JSON-Format zurückgeliefert. Genauso können dann die Daten geändert oder auch neue Datenstäze hinzugefügt werden. Soweit so gut. Diese Methodik läuft gut.

Jetzt möchte ich das Ganze ein bisschen moderner aufziehen und C# WPF nutzen, um die Daten aus der Datenbank anzuzeigen, zu verändern oder neue Datensätze einzufügen. In WPF bestehen Möglichkeiten des Bindings und mit einem SQL-Server auf dem direkter Zugriff besteht funktioniert das auch sehr gut.

Allerdings möchte ich über das Internet kommunizieren und muss über ein Zwischenskript auf die Datenbank zugreifen, da eine direkte Verbindung auf die Datenbank nicht mölgich ist. Wie kann ich in solch einem Fall das Binding von WPF optimal nutzen? Kennt hierfür jemand sehr gute Beispiele, an denen ich mich orientieren kann?

Da es sich bei dem Server um ein NAS-System von Synology handelt, könnte ich auch Anpassungen am Server durchführen um WPF und das Binding möglichst effektiv zu nutzen. Allerdings muss immer auch die Sicherheit gegeben sein.

Falls jemand gute Literatur, gute Tutorial zu einer derartigen Aufgabenstellung hat, wäre ich für jede Information und für jeden Verweis sehr dankbar. Ich habe schon einige Zeit nach etwas geeignetem gesucht, bin aber bisher nicht fündig geworden.