Laden...

Mapping: BusinessObjects -> Dictionary -> BusinessObjects (Reflection? Generic?)

Erstellt von laurasophie vor 15 Jahren Letzter Beitrag vor 15 Jahren 2.156 Views
L
laurasophie Themenstarter:in
14 Beiträge seit 2008
vor 15 Jahren
Mapping: BusinessObjects -> Dictionary -> BusinessObjects (Reflection? Generic?)

Hallo,

da ich leider (noch) keinerlei Erfahrung mit Reflection und Generics habe, hier mein Problem:

Ich benutze zum als allgemeinen Datentyp zur Übertragung zwischen den verschiedenen Layern einer verteilten Anwendung Dictionarys (string, object).
Darin bilde ich auch die Beziehungen gut ab, was ja kein Problem darstellt.
Nur muss so leider pro BusinessObject immer der ganze SetDictionary und GetDictionary manuell angelegt werden... Das nimmt sehr viel Codierzeit in Anspruch.
Gibt es da einen Ansatz das mit Reflection zu lösen? Vielleicht hat ja irgendjemand eine Idee.
Ich poste hier mal kurz einen Ausschnitt eines kleinen Codes der Set und GetDict zum Verständnis.


public override void SetDictionary(Dictionary<string, object> objectValues)
        {
            ObjectID = int.Parse(objectValues["ObjectID"] == null ? "0" : objectValues["ObjectID"].ToString());
            MandantID = int.Parse(objectValues["MandantID"] == null ? "0" : objectValues["MandantID"].ToString());
            MitarbeiterID = int.Parse(objectValues["MitarbeiterID"] == null ? "0" : objectValues["MitarbeiterID"].ToString());
            Nummer = GetStringValue(objectValues["Nummer"]);
            Suchbegriff = GetStringValue(objectValues["Suchbegriff"]);
            Firma1 = GetStringValue(objectValues["Firma1"]);
            Firma2 = GetStringValue(objectValues["Firma2"]);
            Name = GetStringValue(objectValues["Name"]);
            Vorname = GetStringValue(objectValues["Vorname"]);
            Strasse = GetStringValue(objectValues["Strasse"]);
            Land = GetStringValue(objectValues["Land"]);
            Landname = GetStringValue(objectValues["Landname"]);
            PLZ = GetStringValue(objectValues["PLZ"]);
            Ort = GetStringValue(objectValues["Ort"]);
            Telefon1 = GetStringValue(objectValues["Telefon1"]);
            Telefon2 = GetStringValue(objectValues["Telefon2"]);
            Telefax = GetStringValue(objectValues["Telefax"]);
            Handy = GetStringValue(objectValues["Handy"]);
            EMail = GetStringValue(objectValues["EMail"]);
            Internet = GetStringValue(objectValues["Internet"]);
            Bemerkung = GetStringValue(objectValues["Bemerkung"]);
            Notiz = GetStringValue(objectValues["Notiz"]);
            ErsterKontakt = objectValues["ErsterKontakt"] == null ? DateTime.Now : DateTime.Parse(objectValues["ErsterKontakt"].ToString());
            LetzterKontakt = objectValues["LetzterKontakt"] == null ? DateTime.Now : DateTime.Parse(objectValues["LetzterKontakt"].ToString());
            if (objectValues["Geburtsdatum"] != null)
                Geburtsdatum = DateTime.Parse(objectValues["Geburtsdatum"].ToString());
            Warnung = GetStringValue(objectValues["Warnung"]);
            Briefanrede = GetStringValue(objectValues["Briefanrede"]);
            Lieferstop = bool.Parse(objectValues["Lieferstop"] == null ? "false" : objectValues["Lieferstop"].ToString());
            Serienbrief = bool.Parse(objectValues["Serienbrief"] == null ? "true" : objectValues["Serienbrief"].ToString());
            Serienmail = bool.Parse(objectValues["Serienmail"] == null ? "true" : objectValues["Serienmail"].ToString());
            UnsereKundennummer = GetStringValue(objectValues["UnsereKundennummer"]);
            ShopKennung = GetStringValue(objectValues["ShopKennung"]);
            ShopPasswort = GetStringValue(objectValues["ShopPasswort"]);
            ShopUrl = GetStringValue(objectValues["ShopUrl"]);
            EMailRechnung = GetStringValue(objectValues["EMailRechnung"]);
            EMailMahnung = GetStringValue(objectValues["EMailMahnung"]);
            EPaper = bool.Parse(objectValues["EPaper"] == null ? "false" : objectValues["EPaper"].ToString());
            AusweisNummer = GetStringValue(objectValues["AusweisNummer"]);
            AusweisBehoerde = GetStringValue(objectValues["AusweisBehoerde"]);
            if (objectValues["AusweisDatumbis"] != null)
                AusweisDatumbis = DateTime.Parse(objectValues["AusweisDatumbis"].ToString());
            Faul = bool.Parse(objectValues["Faul"] == null ? "false" : objectValues["Faul"].ToString());
            Vorsicht = bool.Parse(objectValues["Vorsicht"] == null ? "false" : objectValues["Vorsicht"].ToString());
            Bank = GetStringValue(objectValues["Bank"]);
            BLZ = GetStringValue(objectValues["BLZ"]);
            Kto = GetStringValue(objectValues["Kto"]);
            BIC = GetStringValue(objectValues["BIC"]);
            IBAN = GetStringValue(objectValues["IBAN"]);
            KreditkartenNummer = GetStringValue(objectValues["KreditkartenNummer"]);
            KreditkartenGesellschaft = GetStringValue(objectValues["KreditkartenGesellschaft"]);
            if (objectValues["KreditkartenDatumbis"] != null)
                KreditkartenDatumbis = DateTime.Parse(objectValues["KreditkartenDatumbis"].ToString());
            Lock = bool.Parse(objectValues["Lock"] == null ? "false" : objectValues["Lock"].ToString());
            Update = objectValues["Update"] == null ? DateTime.Now : DateTime.Parse(objectValues["Update"].ToString());

            if (objectValues.ContainsKey("Art"))
            {
                Dictionary<string, object> art = (Dictionary<string, object>)objectValues["Art"];
                Art = new AddressArt() { Beschreibung = GetStringValue(art["Beschreibung"]), ObjectID = int.Parse(art["ObjectID"] == null ? "0" : art["ObjectID"].ToString()) };
            }
            else
            {
                if (ObjectID == 0)
                {
                    Art = new AddressArt() { Beschreibung = string.Empty, ObjectID = 0 };
                }
            }

            if (objectValues.ContainsKey("Kennung"))
            {
                Dictionary<string, object> kennung = (Dictionary<string, object>)objectValues["Kennung"];
                Kennung = new AddressKennung() { Beschreibung = GetStringValue(kennung["Beschreibung"]), ObjectID = int.Parse(kennung["ObjectID"] == null ? "0" : kennung["ObjectID"].ToString()) };
            }
            else
            {
                if (ObjectID == 0)
                {
                    Kennung = new AddressKennung() { Beschreibung = string.Empty, ObjectID = 0 };
                }
            }

            if (objectValues.ContainsKey("Anrede"))
            {
                Dictionary<string, object> anrede = (Dictionary<string, object>)objectValues["Anrede"];
                Anrede = new AddressAnrede() { Beschreibung = GetStringValue(anrede["Beschreibung"]), ObjectID = int.Parse(anrede["ObjectID"] == null ? "0" : anrede["ObjectID"].ToString()) };
            }
            else
            {
                if (ObjectID == 0)
                {
                    Anrede = new AddressAnrede() { Beschreibung = string.Empty, ObjectID = 0 };
                }
            }

            if (objectValues.ContainsKey("Titel"))
            {
                Dictionary<string, object> titel = (Dictionary<string, object>)objectValues["Titel"];
                Titel = new AddressTitel() { Beschreibung = GetStringValue(titel["Beschreibung"]), ObjectID = int.Parse(titel["ObjectID"] == null ? "0" : titel["ObjectID"].ToString()) };
            }
            else
            {
                if (ObjectID == 0)
                {
                    Titel = new AddressTitel() { Beschreibung = string.Empty, ObjectID = 0 };
                }
            }

            if (objectValues.ContainsKey("Rechnungsanschrift"))
            {
                Dictionary<string, object> rechnungsanschrift = (Dictionary<string, object>)objectValues["Rechnungsanschrift"];
                Rechnungsanschrift = new AddressAnschrift();
                Rechnungsanschrift.ObjectID = int.Parse(rechnungsanschrift["ObjectID"] == null ? "0" : rechnungsanschrift["ObjectID"].ToString());
                Rechnungsanschrift.Firma1 = GetStringValue(rechnungsanschrift["Firma1"]);
                Rechnungsanschrift.Firma2 = GetStringValue(rechnungsanschrift["Firma2"]);
                Rechnungsanschrift.Name = GetStringValue(rechnungsanschrift["Name"]);
                Rechnungsanschrift.Vorname = GetStringValue(rechnungsanschrift["Vorname"]);
                Rechnungsanschrift.Strasse = GetStringValue(rechnungsanschrift["Strasse"]);
                Rechnungsanschrift.Land = GetStringValue(rechnungsanschrift["Land"]);
                Rechnungsanschrift.Landname = GetStringValue(rechnungsanschrift["Landname"]);
                Rechnungsanschrift.PLZ = GetStringValue(rechnungsanschrift["PLZ"]);
                Rechnungsanschrift.Ort = GetStringValue(rechnungsanschrift["Ort"]);
                Rechnungsanschrift.Telefon1 = GetStringValue(rechnungsanschrift["Telefon1"]);
                Rechnungsanschrift.Telefon2 = GetStringValue(rechnungsanschrift["Telefon2"]);
                Rechnungsanschrift.Telefax = GetStringValue(rechnungsanschrift["Telefax"]);
                Rechnungsanschrift.Handy = GetStringValue(rechnungsanschrift["Handy"]);

                if (rechnungsanschrift.ContainsKey("Anrede"))
                {
                    Dictionary<string, object> rechnungsanschriftAnrede = (Dictionary<string, object>)rechnungsanschrift["Anrede"];
                    Rechnungsanschrift.Anrede = new AddressAnrede() { Beschreibung = GetStringValue(rechnungsanschriftAnrede["Beschreibung"]), ObjectID = int.Parse(rechnungsanschriftAnrede["ObjectID"] == null ? "0" : rechnungsanschriftAnrede["ObjectID"].ToString()) };
                }
                else
                {
                    if (Rechnungsanschrift.ObjectID == 0)
                    {
                        Rechnungsanschrift.Anrede = new AddressAnrede() { Beschreibung = string.Empty, ObjectID = 0 };
                    }
                }

                if (rechnungsanschrift.ContainsKey("Titel"))
                {
                    Dictionary<string, object> rechnungsanschriftTitel = (Dictionary<string, object>)rechnungsanschrift["Titel"];
                    Rechnungsanschrift.Titel = new AddressTitel() { Beschreibung = GetStringValue(rechnungsanschriftTitel["Beschreibung"]), ObjectID = int.Parse(rechnungsanschriftTitel["ObjectID"] == null ? "0" : rechnungsanschriftTitel["ObjectID"].ToString()) };
                }
                else
                {
                    if (Rechnungsanschrift.ObjectID == 0)
                    {
                        Rechnungsanschrift.Titel = new AddressTitel() { Beschreibung = string.Empty, ObjectID = 0 };
                    }
                }
            }

            if (objectValues.ContainsKey("Lieferanschrift"))
            {
                Dictionary<string, object> lieferanschrift = (Dictionary<string, object>)objectValues["Lieferanschrift"];
                Lieferanschrift = new AddressAnschrift();
                Lieferanschrift.ObjectID = int.Parse(lieferanschrift["ObjectID"] == null ? "0" : lieferanschrift["ObjectID"].ToString());
                Lieferanschrift.Firma1 = GetStringValue(lieferanschrift["Firma1"]);
                Lieferanschrift.Firma2 = GetStringValue(lieferanschrift["Firma2"]);
                Lieferanschrift.Name = GetStringValue(lieferanschrift["Name"]);
                Lieferanschrift.Vorname = GetStringValue(lieferanschrift["Vorname"]);
                Lieferanschrift.Strasse = GetStringValue(lieferanschrift["Strasse"]);
                Lieferanschrift.Land = GetStringValue(lieferanschrift["Land"]);
                Lieferanschrift.Landname = GetStringValue(lieferanschrift["Landname"]);
                Lieferanschrift.PLZ = GetStringValue(lieferanschrift["PLZ"]);
                Lieferanschrift.Ort = GetStringValue(lieferanschrift["Ort"]);
                Lieferanschrift.Telefon1 = GetStringValue(lieferanschrift["Telefon1"]);
                Lieferanschrift.Telefon2 = GetStringValue(lieferanschrift["Telefon2"]);
                Lieferanschrift.Telefax = GetStringValue(lieferanschrift["Telefax"]);
                Lieferanschrift.Handy = GetStringValue(lieferanschrift["Handy"]);

                if (lieferanschrift.ContainsKey("Anrede"))
                {
                    Dictionary<string, object> lieferanschriftAnrede = (Dictionary<string, object>)lieferanschrift["Anrede"];
                    Lieferanschrift.Anrede = new AddressAnrede() { Beschreibung = GetStringValue(lieferanschriftAnrede["Beschreibung"]), ObjectID = int.Parse(lieferanschriftAnrede["ObjectID"] == null ? "0" : lieferanschriftAnrede["ObjectID"].ToString()) };
                }
                else
                {
                    if (Lieferanschrift.ObjectID == 0)
                    {
                        Lieferanschrift.Anrede = new AddressAnrede() { Beschreibung = string.Empty, ObjectID = 0 };
                    }
                }

                if (lieferanschrift.ContainsKey("Titel"))
                {
                    Dictionary<string, object> lieferanschriftTitel = (Dictionary<string, object>)lieferanschrift["Titel"];
                    Lieferanschrift.Titel = new AddressTitel() { Beschreibung = GetStringValue(lieferanschriftTitel["Beschreibung"]), ObjectID = int.Parse(lieferanschriftTitel["ObjectID"] == null ? "0" : lieferanschriftTitel["ObjectID"].ToString()) };
                }
                else
                {
                    if (Lieferanschrift.ObjectID == 0)
                    {
                        Lieferanschrift.Titel = new AddressTitel() { Beschreibung = string.Empty, ObjectID = 0 };
                    }
                }
            }
        }

        public override Dictionary<string, object> GetDictionary()
        {
            Dictionary<string, object> retValues = new Dictionary<string, object>();

            retValues["ObjectID"] = ObjectID;
            retValues["MandantID"] = MandantID;
            retValues["MitarbeiterID"] = MitarbeiterID;
            retValues["Nummer"] = Nummer;
            retValues["Suchbegriff"] = Suchbegriff;
            retValues["Firma1"] = Firma1;
            retValues["Firma2"] = Firma2;
            retValues["Name"] = Name;
            retValues["Vorname"] = Vorname;
            retValues["Strasse"] = Strasse;
            retValues["Land"] = Land;
            retValues["Landname"] = Landname;
            retValues["PLZ"] = PLZ;
            retValues["Ort"] = Ort;
            retValues["Telefon1"] = Telefon1;
            retValues["Telefon2"] = Telefon2;
            retValues["Telefax"] = Telefax;
            retValues["Handy"] = Handy;
            retValues["EMail"] = EMail;
            retValues["Internet"] = Internet;
            retValues["Bemerkung"] = Bemerkung;
            retValues["Notiz"] = Notiz;
            retValues["ErsterKontakt"] = ErsterKontakt;
            retValues["LetzterKontakt"] = LetzterKontakt;
            retValues["Geburtsdatum"] = Geburtsdatum;
            retValues["Warnung"] = Warnung;
            retValues["Briefanrede"] = Briefanrede;
            retValues["Lieferstop"] = Lieferstop;
            retValues["Serienbrief"] = Serienbrief;
            retValues["Serienmail"] = Serienmail;
            retValues["UnsereKundennummer"] = UnsereKundennummer;
            retValues["ShopKennung"] = ShopKennung;
            retValues["ShopPasswort"] = ShopPasswort;
            retValues["ShopUrl"] = ShopUrl;
            retValues["EMailRechnung"] = EMailRechnung;
            retValues["EMailMahnung"] = EMailMahnung;
            retValues["EPaper"] = EPaper;
            retValues["AusweisNummer"] = AusweisNummer;
            retValues["AusweisBehoerde"] = AusweisBehoerde;
            retValues["AusweisDatumbis"] = AusweisDatumbis;
            retValues["Faul"] = Faul;
            retValues["Vorsicht"] = Vorsicht;
            retValues["Bank"] = Bank;
            retValues["BLZ"] = BLZ;
            retValues["Kto"] = Kto;
            retValues["BIC"] = BIC;
            retValues["IBAN"] = IBAN;
            retValues["KreditkartenNummer"] = KreditkartenNummer;
            retValues["KreditkartenGesellschaft"] = KreditkartenGesellschaft;
            retValues["KreditkartenDatumbis"] = KreditkartenDatumbis;
            retValues["Lock"] = Lock;
            //retValues["Update"] = Update;
            retValues["Update"] = DateTime.Now;

            if (Art != null)
            {
                Dictionary<string, object> art = new Dictionary<string, object>();
                art["ObjectID"] = Art.ObjectID;
                art["Beschreibung"] = Art.Beschreibung;
                retValues["Art"] = art;
            }

            if (Kennung != null)
            {
                Dictionary<string, object> kennung = new Dictionary<string, object>();
                kennung["ObjectID"] = Kennung.ObjectID;
                kennung["Beschreibung"] = Kennung.Beschreibung;
                retValues["Kennung"] = kennung;
            }

            if (Anrede != null)
            {
                Dictionary<string, object> anrede = new Dictionary<string, object>();
                anrede["ObjectID"] = Anrede.ObjectID;
                anrede["Beschreibung"] = Anrede.Beschreibung;
                retValues["Anrede"] = anrede;
            }

            if (Titel != null)
            {
                Dictionary<string, object> titel = new Dictionary<string, object>();
                titel["ObjectID"] = Titel.ObjectID;
                titel["Beschreibung"] = Titel.Beschreibung;
                retValues["Titel"] = titel;
            }

            if (Rechnungsanschrift != null)
            {
                Dictionary<string, object> rechnungsAnschrift = new Dictionary<string, object>();
                rechnungsAnschrift["ObjectID"] = Rechnungsanschrift.ObjectID;
                retValues["Rechnungsanschrift"] = rechnungsAnschrift;
            }

            if (Lieferanschrift != null)
            {
                Dictionary<string, object> lieferAnschrift = new Dictionary<string, object>();
                lieferAnschrift["ObjectID"] = Lieferanschrift.ObjectID;
                retValues["Lieferanschrift"] = lieferAnschrift;
            }

            return retValues;
        }

2.187 Beiträge seit 2005
vor 15 Jahren

Hallo laurasophie,

Dafür kann man mit Reflection eine Lösung erstellen.
Eventuell würde sich aber auch Serialisierung oder so etwas anbieten, das müsste man nicht selbst implementieren.

Ungetesteter Code für Reflection-Lösung:


  public class DicitionaryConverter
  {
    private List<Type> _IntegraleTypen = new List<Type>(new Type[] { 
      typeof(int),
      typeof(string),
      typeof(decimal),
      typeof(DateTime)
      // ...
    });

    public virtual Dictionary<string, object> ToDictionary(object obj)
    {
      Dictionary<string, object> re = new Dictionary<string, object>();
      if (obj != null)
      {
        Type te = obj.GetType();
        foreach (System.Reflection.PropertyInfo pi in te.GetProperties())
        {
          if (this._IntegraleTypen.Contains(pi.PropertyType))
          {
            re.Add(pi.Name, pi.GetValue(obj, new object[] { }));
          }
          else
          {
            re.Add(pi.Name, ToDictionary(pi.GetValue(obj, new object[] { })));
          }
        }
      }
      return re;
    }

    public virtual void FromDictionary(Dictionary<string, object> dicitionary, object obj)
    {
      if (obj != null && dicitionary != null)
      {
        Type te = obj.GetType();
        foreach (System.Reflection.PropertyInfo pi in te.GetProperties())
        {
          if (dicitionary.ContainsKey(pi.Name))
          {
            Dictionary<string, object> subValues = dicitionary[pi.Name] as Dictionary<string, object>;
            if (subValues != null)
            {
              this.FromDictionary(subValues, pi.GetValue(obj, new object[] { }));
            }
            else
            {
              pi.SetValue(obj, dicitionary[pi.Name], new object[] { });
            }
          }
        }
      }
    }
  }

Gruß
Juy Juka

L
laurasophie Themenstarter:in
14 Beiträge seit 2008
vor 15 Jahren

Hallo JuyJuka,

vielen Dank für Deine Antwort!!!
Das ging ja Super-Schnell!

Das mit dem Serialisieren, lass ich mal lieber, da Dictionarys nicht so richtig gehen. Aber für einen einheitlichen und neutralen Datenaustausch, zwischen DAL und BusinessLayer eignen sie sich, meiner Meinung nach, am besten um auch Hierarchische Strukturen mit abzubilden. Du kannst mich gerne korrigieren, da ich noch Anfänger bin!

Ich habe keinerlei Erfahrung mit dem Reflection und werde mir nun mal Deinen Code näher ansehen und hoffen, dass ich das verstehe und so umsetzen kann. Vielleicht kannst Du mir ja noch etwas dazu erklären...
Das ganze muss bei mir ja eigentlich nur so funktionieren:

Set:

BO.Name = dictionary["Name"].ToString();
bzw.
if (BO.Geburtsdatum != null)
BO.Geburtsdatum = DateTime.Parse(dictionary["Geburtsdatum"].ToString());

Get:

dictionary["Name"] = BO.Name;
dictionary["Name"] = BO.Geburtsdatum;

Wie mache ich in Deinem Code eigentlich die if Anweisungen bei Null usw.?

Vielen Dank nochmal für Deinen guten Ansatz!

Viele Grüße
Manuel

2.187 Beiträge seit 2005
vor 15 Jahren

Hallo laurasophie,

Serialisierung ist für den Datenaustausch gedacht.
In .Net gibt's für so was auch DataSet's.

Der Datenaustausch muss ja nicht neutral sein, er sollte ehr generisch sein. Dann ist er allgemeingültig und auch Typensicher. Dafür gibts Interfaces.

Wenn ich Muße habe, dann schreib ich noch Kommentare zu meinem Code.

Gruß
Juy Juka

L
laurasophie Themenstarter:in
14 Beiträge seit 2008
vor 15 Jahren

Hallo,

nein musst Du wirklich nicht. Ich habe es bis hierher verstanden. Vielen, vielen Dank. Hab wirklich viel dazu gelernt.

Du würdest also sogenannte DataTransferObjecte einsetzen bzw. diese mit Interfaces kombinieren?
Hab ich gerade irgendwo gegoogelt...

VG
Manuel

L
laurasophie Themenstarter:in
14 Beiträge seit 2008
vor 15 Jahren

Hallo,

nur zur Info, ich habe nun zwei Methoden, einmal zum mapping in ein Dictionary und danach wieder in die Quellobjekte zurück erstellt.

Für Verbesserungsvorschläge bin ich jederzeit offen!!!


public class DictConv
    {
        private List<Type> _IntegraleTypen = new List<Type>(new Type[] { typeof(int), typeof(string), typeof(DateTime) });

        public Dictionary<string, object> ToDictionary(object obj)
        {
            Dictionary<string, object> re = new Dictionary<string, object>();
            if (obj != null)
            {
                Type te = obj.GetType();
                foreach (System.Reflection.PropertyInfo pi in te.GetProperties())
                {
                    if (this._IntegraleTypen.Contains(pi.PropertyType))
                    {
                        re.Add(pi.Name, pi.GetValue(obj, new object[] { }));
                    }
                    else
                    {
                        re.Add(pi.Name, ToDictionary(pi.GetValue(obj, new object[] { })));
                    }
                }
            }
            return re;
        }

        public object FromDictionary(Dictionary<string, object> dictionary, object obj)
        {
            if (obj != null && dictionary != null)
            {
                Type te = obj.GetType();
                foreach (System.Reflection.PropertyInfo pi in te.GetProperties())
                {
                    if (dictionary.ContainsKey(pi.Name))
                    {
                        Dictionary<string, object> subValues = dictionary[pi.Name] as Dictionary<string, object>;
                        if (subValues != null)
                        {
                            Type ti = pi.PropertyType;
                            object subObj = Activator.CreateInstance(ti);
                            pi.SetValue(obj, this.FromDictionary(subValues, subObj), new object[] { });
                        }
                        else
                        {
                            pi.SetValue(obj, dictionary[pi.Name], new object[] { });
                        }
                    }
                }
            }
            return obj;
        }
    }

2.187 Beiträge seit 2005
vor 15 Jahren

Hallo laurasophie,

Wenn du Activator.CreateInstance verwendest, kannst du bei der FromDictionary-Methode auch darauf verzichten, ein Objekt von Ausen mit zu geben (das war in der Ursprünglichen Signatur, nur um Activater.CreateInstance zu vermeiden):


public T FromDictionary<T>(Dictionary<string, object> dictionary)
where T : class, new()
{
  T obj = new T();
  // ...
  return obj;
}

Ein Property muss keine set- oder get-Methode haben, das wird bei Reflection nicht geprüft und löst erst zur Laufzeit einen Fehler aus.

Außerdem Solltest du unbedingt die Microsoft-Benennungsrichtlinien beachten => !! Keine Abkürzungen !! ( MSDN: Richtlinien für die Benennung )

Gruß
Juy Juka

L
laurasophie Themenstarter:in
14 Beiträge seit 2008
vor 15 Jahren

Hallo Juy Juka,

vielen Dank für Deine Hilfe.
Ich werde die Namenskonventionen beachten und die Variablen noch umbennenen. Es war nur zum Testen so.

Das mit dem T versteh ich gerade nicht so, da ich die beiden Methoden in eine eigene Assembly auslagern möchte und sie von aussen aufrufen werde. Das heisst ich gebe ein Objekt mit rein, in das mit den Werten des auch hereingegebenen Dictionarys gefüllt werden sollte. Als Rückgabeobjekt sollte dann das gefüllte, hereingegebende Objekt zurückgegeben werden.

Eine andere Methode als Activater.CreateInstance fällt mir nicht ein, um die "Unterobjekte" zu erstellen und zurückzugeben? Gibts da einen anderen Ansatz?

Danke.

Gruß
laurasophie

2.187 Beiträge seit 2005
vor 15 Jahren

Hallo laurasophie,

Activator.CreateInstance erfordert immer einen parameterlosen, öffentlichen Konstruktor, das ist dann eine Fehlerquelle, daher ist "<T> ... new()" besser.
Die Unterobjekte sollten am Besten schon da sein, ansonsten hat man halt wieder die Fehlerquelle mit Activator.CreateInstance.
Aber eine bessere Lösung als Activator.CreateInstance ist mir auch nicht bekannt, man kann es nur vermeiden, wo es nicht nötig ist.

Um auf eine ältere Frage von dir zurück zu kommen: Ich würde DataTransferObjecte(+Interfaces) unsicheren Lösungen wie XML, DataTable oder Dictionary vorziehen.

Gruß
Juy Juka

L
laurasophie Themenstarter:in
14 Beiträge seit 2008
vor 15 Jahren

Danke. Ich überdenke die Entscheidung mit Dictionarys nochmal.

Bei DTO's muss ich auch wieder manuell mappen, oder?
Wie müsste ich die DTO's mit Interfaces dann umsetzen? Hast Du da einen Anhaltspunkt.

Gruß
laurasophie

2.187 Beiträge seit 2005
vor 15 Jahren

Hallo laurasophie,

Da gibt's viele ansätze. Du müsstest schon verraten, wei deine Grobe Architektur aussieht:

  • Architekturstiel (Piepes&Filter, Layer, Brocker, ...)
  • Verteilte Anwendung oder nicht
  • Verwendete Frameworks

Versuch auch an die Zukunft deiner Software zu denken, falls diese nicht in 1-2Tagen in die Tonne wandert 😃

Gruß
Juy Juka

L
laurasophie Themenstarter:in
14 Beiträge seit 2008
vor 15 Jahren

Hallo JuyJuka,

ich denke sehr viel an die Zukunft der Software, darum bin ich mir mit der Dictionary-Lösung nicht so ganz zufrieden...

Die Software:

C#, .NET 3.5 SP1, VS2008, SQL-Server 2008, Entity Framework, WCF, Windows Form oder WPF (eher Windows Form!).

Es handelt sich um eine verteilte Anwendung und ich habe die Anwendung in verschieden Layer aufgeteilt...

Sql-Server 2008 <-> DataLayerEFSqlSrv(EntityFramework) <-> DataLayerInterface <-> Dictionary<string, object> <-> BusinessLogic <-> BusinessEntities <-> ServiceInterface(WCF) <-> ServiceImplementation(WCF) <-> BusinessEntities(serialisiert) <-> Client-UI (WinForms)

Bedenken an der ganzen Sache, macht mir bis jetzt diese ganze Menge Codierarbeit beim Mapping von der DataLayerEFSqlSrv als Dictionary in die BusinessEntities und im gegenzug natürlich wieder zurück. Man hat in meiner ersten Lösung in den BusinessEntities pro Klasse je eine Set und Get-Dictionary Methode und in der Entities-Klasse im DataLayerEFSqlDrv auch in jeder Klasse je eine Set und Get-Dictionary!!! Ich habe jetzt zwar diese Generische Methode, jedoch sind die Tabellen im EF und die BusinessObjects unterschiedlich, wodurch ich den Einsatz der Generics Methoden nur auf der BusinessLogic Seite einsetzen kann...

Ich kann Dir auch gerne mal den SourceCode zur Verfügung stellen...

Ich denke gerade noch an einen Einsatz in der Art:

http://www.hadihariri.com/blogengine/2007/12/default.aspx

Was meinst Du dazu? Oder was meintest Du mit DTO und Interfaces? Man könnte ja direkt meine BusinessEntities als DTO's verwenden und dann noch die notwendigen Methoden erst im Client oder BusinessLogic zur Schnittstelle addieren.

Viele Grüße
Manuel

84 Beiträge seit 2007
vor 15 Jahren

In diesem Zusammenhang ist vielleicht folgender Artikel ganz interessant:

"The Entity Framework In Layered Architectures"
http://msdn.microsoft.com/en-us/magazine/cc700340.aspx

L
laurasophie Themenstarter:in
14 Beiträge seit 2008
vor 15 Jahren

Hallo Razer,

ich habe meine Applikation mal auf der neuesten Basis des Templates einer Modularen Geschäftsanwendung einer „Proof-of-Concept“ Studie im Microsoft Technology Center (MTC) in Unterschleißheim aufgebaut.

Meine BusinessEntities enthalten jedoch auch Validierungsmethoden usw., welche ich im DataLayer ja noch nicht brauche und auch nicht bekanntmachen möchte.

Ich dachte nun eine eine partielle Klasse (Business-Entities), die erst im Client mit der notwendigen Validierungs-Logic erweitert wird!?

Was meint ihr zu dem Ansatz?

VG
Manuel

Allen noch ein frohes und gesundes neues Jahr...

2.187 Beiträge seit 2005
vor 15 Jahren

Hallo laurasophie,

partial kann man ganz schnell wieder vergessen. Dieses Schlüsselwort ist nur zum aufteilen des Quellecodes einer Klasse in mehrer Dateien gedacht und ist nach dem Kompilieren einfach weg.

Gruß
Juy Juka

L
laurasophie Themenstarter:in
14 Beiträge seit 2008
vor 15 Jahren

Hallo JuyJuka,

was würdest Du mir vorschlagen?

Viele Grüße
laurasophie

2.187 Beiträge seit 2005
vor 15 Jahren

Hallo laurasophie,

Leider kenn ich den "Proof-of-Concept" nicht. Könntest du ein Diagramm dazu erstellen? (Dein Beispiel würde reichen, es muss kein allgemeingültiges Diagramm werden 😃 )

Gruß
Juy Juka

84 Beiträge seit 2007
vor 15 Jahren

Hallo laurasophie,

Um ehrlich zu sein bin ich gerade mit einem ganz ähnlichem Problem beschäftigt.
In meinem Fall handelt es sich allerdings um eine WinForms-Anwendung, bei der die Layer keine physischen Grenzen überwinden müssen, d.h. es gibt keinen Application-Server oder etwas vergleichbares.
Die Schichten dienen damit eher einem sauberen Aufbau und einer wartbaren Grundarchitektur.

Derzeit habe ich auch noch keine wirklich befriedigende Antwort gefunden. Aktuell fasse ich die Entitys als Teil eines Contracts auf, d.h. jedes Projekt einer Schicht referenziert dann halt das Entity-Model mit den EF-Klassen.

Dummerweise steckt in diesem dann natürlich auch die DataAccess Logik.
Der Umweg über selbstgeschriebene Ersatzklassen ist mir eindeutig zu aufwendig, ich versuche es wenn dann auch über Schnittstellen hinzubekommen, alles manuell quasi doppelt zu schreiben, dass kann es doch irgendwo nicht sein.

84 Beiträge seit 2007
vor 15 Jahren

Hallo laurasophie,

Gruß
Juy Juka

Ist es nicht so von MS gedacht gewesen, dass man die Geschäftslogik tatsächlich in solchen partiellen Klassen unterbringt?
(auch ich halte es für ein fragwürdig Konzept)

Gruß,
Razer

L
laurasophie Themenstarter:in
14 Beiträge seit 2008
vor 15 Jahren

Hallo Razer,

also auch die Microsoft Entwickler verwenden globale Entities, nicht jedoch die vom EF oder LinqToSql.
Ich habe dies nun gerade auch so umgesetzt und verwende aber als Übergabetyp vom BusinessLayer zum DataLayer ein Dictionary<string, object>, wobei ich mit zwei Hilfsmethoden die wenigsten auf der BusinessLayer Seite die Objekte von und zu Dictionarys konvertieren. Lediglich auf der DataLayer Seite muss man noch alles manuell Mappen...

2.187 Beiträge seit 2005
vor 15 Jahren

Hallo Razer,

Ist es nicht so von MS gedacht gewesen, dass man die Geschäftslogik tatsächlich in solchen partiellen Klassen unterbringt?
(auch ich halte es für ein fragwürdig Konzept)

Das Schlüsselwort worde eingeführt, um generierten Quellcode von selbst geschriebenem Quellcode zu trennen. Es ist nicht im geringsten für das saubere Design von Software geeignet, da es aus Design-Sicht nichts von einenander entkoppelt, sondern genau das gegenteil macht.

Nicht verteilte Anwendungen entwickle ich auch. Dafür habe ich eine generische Datenzugriffschicht, wodurch ich nur noch die Businesschicht(en) schreiben. (hier)

Gruß
Juy Juka