Kursvorbereitung / C#.NET Interface-Konzept

C#.NET Interface-Konzept

C#.NET Interface-Konzept

In größeren Projekten geht man gern so vor: zuerst wird der gesamte Entwurf in einigen Interfaces deklariert; anschließend machen sich die Developer an die Teil-Implementierung.

Zuerst die Interfaces:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace cs_schulung
{
  public interface IOrt
  {
    int ID { get; set; }
    string Name { get; set; }
    void Add(IMensch x);
    List<IMensch> Menschliste { get; }
  }
  public interface IMensch
  {
    int ID { get; set; }
    string Nachname { get; set; }
    string Vorname { get; set; }
    double Gehalt { get; set; }
    void Add(IKauf x);
    List<IKauf> Kaufliste { get; }
    IOrt Stadt { get; set; }
  }
  public interface IKauf
  {
    int ID { get; set; }
    int IDMensch { get; set; }
    string Artikel { get; set; }
    double Einzelpreis { get; set; }
    int Anzahl { get; set; }
    double Gesamt { get; }
    IMensch Kunde { get; set; }
  }
}

Die Klasse Ort implementiert das Interface IOrt. Nach der automatischen Generierung der public-Methoden bzw. Properties bleibt nur noch die Detail-Implementierung.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace cs_schulung
{
  public class Ort : IOrt
  {
    private int _ID;
    private string _Name;
    private List<IMensch> _menschliste = new List<IMensch>();
    public Ort(int ID, string Name, List<IMensch> menschliste, int iD, string name)
    {
      _ID = ID;
      _Name = Name;
      _menschliste = menschliste;
      this.ID = iD;
      this.Name = name;
    }
    public Ort()
    {
    }
    public int ID { get => this._ID; set => this._ID=value; }
    public string Name { get => this._Name; set => this._Name=value; }
    public List<IMensch> Menschliste { get => this._menschliste; }
    public void Add(IMensch x)
    {
      x.Stadt = this;
      this._menschliste.Add(x);
    }
    public override string ToString()
    {
      return String.Format("ID: {0}, Name: {1}", ID, Name);
    }
  }
}

Ähnlich verläuft das mit der Klasse Mensch, die das Interface IMensch implementiert. Um spätere Ergebnisse sortieren zu können, benötigen Sie noch die Implementierung über IComparable.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace cs_schulung
{
  public class Mensch : IMensch, IComparable
  {
    private int _ID;
    private string _Nachname, _Vorname;
    private double _Gehalt;
    private List<IKauf> _kaufliste = new List<IKauf>();
    private IOrt _Stadt;
    public int ID { get => this._ID; set => this._ID=value; }
    public string Nachname { get => this._Nachname; set => this._Nachname=value; }
    public string Vorname { get => this._Vorname; set => this._Vorname=value; }
    public double Gehalt { get => this._Gehalt; set => this._Gehalt=value; }
    public List<IKauf> Kaufliste { get { return this._kaufliste; } }
    public IOrt Stadt { get => this._Stadt; set => this._Stadt=value; }
    public void Add(IKauf x)
    {
      x.Kunde = this;
      this._kaufliste.Add(x);
    }
    public int CompareTo(object obj)
    {
        IMensch im = (IMensch)obj;           
        return Gehalt.CompareTo(im.Gehalt);
    }
    public override string ToString()
    {
      return String.Format("ID: {0}, Name: {1}, VN: {2}", ID, Nachname, Vorname);
    }
  }
}

Bei der Klasse Kauf läuft es analog:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace cs_schulung
{
  public class Kauf : IKauf
  {
    private int _ID, _IDMensch, _Anzahl;
    private string _Artikel;
    private double _einzelpreis;
    private IMensch _Kunde;
    public int ID { get => this._ID; set => this._ID=value; }
    public int IDMensch { get => this._IDMensch; set => this._IDMensch=value; }
    public string Artikel { get => this._Artikel; set => this._Artikel=value; }
    public double Einzelpreis { get => this._einzelpreis; set => this._einzelpreis=value; }
    public int Anzahl { get => this._Anzahl; set => this._Anzahl=value; }
    public double Gesamt { get { return (Anzahl*Einzelpreis); } }
    public IMensch Kunde { get => this._Kunde; set => this._Kunde = value; }
    public override string ToString()
    {
      return String.Format("ID: {0}, Artikel: {1}, Gesamt: {2}", ID, Artikel, Gesamt);
    }
  }
}

In einem ersten einfachen Test erkennen wir die Zusammenhänge schnell:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace cs_schulung
{
  class Program
  {
    static void Main(string[] args)
    {
      Console.ReadLine();
    }
    // liest via System.Xml.XmlDocument() ein XML-Dokument in eine List<IOrt>
    static List<IOrt> ReadXML(string filename)
    {
      List<IOrt> ortliste = new List<IOrt>();
      System.Xml.XmlDocument dom = new System.Xml.XmlDocument();
      dom.Load(filename);
      foreach (System.Xml.XmlElement eo in dom.SelectNodes("//Ort"))
      {
        IOrt o = new Ort();
        o.ID = Int32.Parse(eo.SelectSingleNode("id").InnerText);
        o.Name = eo.SelectSingleNode("name").InnerText;
        ortliste.Add(o);
        foreach (System.Xml.XmlElement em in eo.SelectNodes("Mensch"))
        {
          IMensch m = new Mensch();
          m.ID = Int32.Parse(em.SelectSingleNode("id").InnerText);
          m.Nachname = em.SelectSingleNode("name").InnerText;
          m.Vorname = em.SelectSingleNode("vorname").InnerText;
          m.Gehalt = Double.Parse(em.SelectSingleNode("Gehalt").InnerText);
          o.Add(m);
          foreach (System.Xml.XmlElement ek in em.SelectNodes("Kauf"))
          {
            IKauf k = new Kauf();
            k.Anzahl = Int32.Parse(ek.SelectSingleNode("anzahl").InnerText);
            k.Artikel = ek.SelectSingleNode("bez").InnerText;
            string einzelpreis = ek.SelectSingleNode("preis").InnerText;
            k.Einzelpreis = Convert.ToDouble(einzelpreis, System.Globalization.CultureInfo.InvariantCulture);
            m.Add(k);
          }
        }
      }
      return ortliste;
    }
    // Alternative: Auswerten mit LINQ
    // liest ein XML-Dokument via System.Xml.Linq.XDocument in List<IOrt>
    static List<IOrt> ReadXMLByLINQ(string filename)
    {
      List<IOrt> ortliste = new List<IOrt>();
      System.Xml.Linq.XDocument xdoc = System.Xml.Linq.XDocument.Load(filename);
      IEnumerable<System.Xml.Linq.XElement> iOrt = xdoc.Descendants("Ort");
      foreach(System.Xml.Linq.XElement iio in iOrt)
      {
        Ort vort = new Ort();
        vort.Name = iio.Element("name").Value;
        vort.ID = Int32.Parse(iio.Element("id").Value);        
        IEnumerable<System.Xml.Linq.XElement> iMensch = iio.Descendants("Mensch");
        foreach (System.Xml.Linq.XElement iim in iMensch)
        {
          Mensch m = new Mensch();
          m.Nachname = iim.Element("name").Value;
          m.Vorname = iim.Element("vorname").Value;
          m.Gehalt = Double.Parse( iim.Element("Gehalt").Value);
          m.ID = Int32.Parse(iim.Element("id").Value);          
          vort.Add(m);
          IEnumerable<System.Xml.Linq.XElement> iKauf = iim.Descendants("Kauf");
          foreach (System.Xml.Linq.XElement iik in iKauf)
          {
            Kauf k = new Kauf();
            k.Artikel= iik.Element("bez").Value;
            // weitere Datenübernahmen
            m.Add(k);
          }
        }
        ortliste.Add(vort);
      }
      return ortliste;
    }
  }
}

Das zurückgegebene Objekt hat in beiden Fällen dieselbe Struktur. Interessant sind die Varianten der Auwertung. Betrachten Sie zunächst die Arbeit über die Schnittstellenobjekte (jedes eingelesene Ort-Objekt wird über dessen Interface IOrt ansprechbar.


foreach (IOrt o in ReadXML(@"C:\wg\Ort_Elemente.xml"))
{
    Console.WriteLine(o);
    // Damit das funktioniert, 
    // muss das Interface IComparable implementiert sein
    // siehe Klasse Mensch
    o.Menschliste.Sort();
    foreach (IMensch xm in o.Menschliste)
    {
        if(xm.Gehalt < 1000)
        {                    
            Console.WriteLine("\t{0} verdient {1:N2} Euro", xm, xm.Gehalt);
            //Hier könnten Sie noch weitermachen:
            //foreach (IKauf xk in xm.Kaufliste)
            //{
            //    Console.WriteLine("\t\t{0}", xk);
            //}
        }
    }
}

Die Alternative liegt in der Auwertung durch LINQ.


var vortliste = ReadXMLByLINQ((@"C:\wg\Ort_Elemente.xml"));
var vorte = from vort in vortliste
            orderby vort.Name ascending
            select vort;
foreach (var ort in vorte)
{
    Console.WriteLine("ID: {0}, Name: {1}", ort.ID, ort.Name);
    var vm = from v_m in ort.Menschliste
                where v_m.Gehalt < 1000
                orderby v_m.Gehalt descending
                select v_m;
    foreach (var m in vm)
    {
        anzahl++;
        Console.WriteLine("\t{0} verdient {1} Euro", m.Nachname, m.Gehalt);
    }
}

wg / 11. Mai 2018



Fragen? Anmerkungen? Tips?

Bitte nehmen Sie Kontakt zu mir auf.






Vielen Dank für Ihr Interesse an meiner Arbeit.


V.i.S.d.P.: Wilfried Grupe * Klus 6 * 37643 Negenborn

☎ 0151. 750 360 61 * eMail: info10@wilfried-grupe.de

www.wilfried-grupe.de/cs_OOP_Interface_Ort_Mensch_Kauf.html