.NET GUI

.NET Community rund um alle Graphical User Interface (GUI) Themen.
Willkommen bei .NET GUI. Anmeldung | Registrieren | Hilfe | Impressum | Forumsregeln
in Suchen

Konzept zur erstellung einer neuen Software

Letzter Beitrag 08-25-2008 9:54 von Norbert Eder. 3 Antworten.
Seite 1 von 1 (4 Treffer)
Beiträge sortieren: Zurück Weiter
  • 08-21-2008 13:20

    Konzept zur erstellung einer neuen Software


    Hi,

    wie im anderen Thread schon gesagt wollte ich nun einmal unser Vorhaben genauer erläutern. Vielleicht
    habt ihr ja Tipps und Ratschläge wie wir einiges anders/besser machen könnten um zu unserem Ziel zu
    gelangen.

    Unsere aktuelle Software ist in VB6 geschrieben. Wir haben uns dazu entschieden auf .NET WPF umzusteigen
    weil wir uns erhoffen, daß diese neue Technologie uns genug Flexibilität und Möglichkeiten bietet um
    den Ansprüchen unserer Kunden sowie unseren eigenen Ansprüchen zu genügen.
    Wir beschäftigen uns dabei allerdings nur mit der Softwareseite. Die Datenbank wollen wir weiterhin so
    übernehmen. Die DB ist MSSQL 2005 bzw. bald 2008 und relativ gut optimiert.

    Unser Hauptaugenmerk bei der Planung liegt momentan bei dem "Framework".
    Wir wollen Masken zur Laufzeit erstellen. Dabei sollen diese Natürlich auch flexibel erweiterbar sein durch
    uns sowie durch den Kunden. Die Möglichkeit eigene Funktionalitäten zu hinterlegen muss auch vorhanden sein.
    Wenn man so will kann man sagen, dass das Projekt durch den Kunden beliebig erweiterbar ist - fast wie ein CRM.
    Natürlich heisst beliebig erweiterbar nur, dass er im Rahmen bestimmter Systemvorgaben Masken,Controls etc verändern
    kann.



    Wir wollen eine TemplateEngine die uns Masken zur Laufzeit dynamisch erstellt. Dabei bekommt die TemplateEngine vorgaben
    durch XAML in welchen Bereichen der Maske sie welchen Content darstellen soll. Wenn ihr den anderen Thread noch in
    Erinnerung habt soll z.b. eine Bestellung-Erfassungsmaske in Bereich 3 dargestellt werden. Die Aufteilung dieser Bereich
    soll durch Schemen geschehen. Desweiteren gibt es nicht nur Gesamtschemen sondern auch Maskenschemen. Diese sollen beschreiben
    an welcher Stelle ein Erfassungsfeld ist, ob es readonly ist oder nicht und welche Funktionalität dahinter steckt. Dabei
    ist auch die Abhängigkeit sehr wichtig. Um z.b. den Gesamtpreis einer Bestellung auszurechnen muss erst die Stückzahl und der
    Artikel eingegeben werden. Diese Abhängigkeiten, die Reihenfolge der Controls etc wollen wir in der Datenbank haben weil es uns
    Zahlreiche vorteile bietet. So können wir z.b. durch ein einfaches SQL Skript beim Kunden die halbe Software umgestalten :-)



    In der Ansicht sieht man schon eine Entität. Diese soll auf eine übergebene Tabelle zugreifen. Besitzt die Tabelle keine Zuordnung
    von Logik zu einer Klasse, oder Anzeigereihenfolge auf der Maske etc. soll die Tabelle trotzdem durch die TemplateEngine erstellt
    werden so, dass auch Daten für diese Tabelle erfasst und gespeichert / geändert werden können. Wenn wir diese Zuordnungen herstellen
    haben wir im Endeffekt dann unsere Klasse z.b. Bestellung die uns die Funktionalitäten bietet die wir an der Stelle benötigen.

    Wir wollen uns mit dem Framework möglichst viele Möglichkeiten offen halten. Da wir bis jetzt allerdings nur mit VB6 gearbeitet haben
    sind wir die Methodik von .Net,WPF und C# nicht gewohnt bzw. wir wissen noch garnicht so richtig was eigentlich alles möglich ist.

    Ich erhoffe mir von diesem Thread das vielleicht ein paar Konzeptideen, Ratschläge oder Ansätze wie wir das ganze angehen sollten.

    Vielen Dank im Voraus
    • Beitragspunkte: 20
    • IP-Adresse ist Registriert
  • 08-22-2008 11:27 Antwort zu

    • Norbert Eder
    • Top 10 Mitwirkender
      Männlich
    • Registriert am 04-09-2008
    • Graz / Austria
    • Beiträge 502
    • Punkte 7.469
    • ForumsAdministrator

    AW: Konzept zur erstellung einer neuen Software

    Also soll es nicht so sein, dass diese Änderungen/Erweiterungen zur Laufzeit vorgenommen werden, sondern durchaus in weiterer Folge als DLL etc. zur Verfügung gestellt werden? D.h. beispielsweise designed der Kunde eine neue Entität und daraus wird dann eine View, das notwendige SQL-Script, evntuell, falls vorhanden, ein NHibernate-Mapping etc. generiert?

    Grundsätzlich läßt sich dies - als Beispiel - mit Hilfe von StringTemplate lösen. D.h. es wird eine Definitionsdatei erstellt. Diese beschreibt Eigenschaften, implementierte Interfaces usw. Daraus läßt sich in weiterer Folge einiges generieren:

    • Entität
    • SQL-Script/Tabellendefinition
    • Mapping-Files beispielsweise für Hybernate
    • View inkl. Databinding

    Die Zwischenstücke müssen natürlich in generischer Form vorliegen. Idealerweise verwendest du dazu eines der bekannten Patterns (MVC, MVVM, MVP, etc.). Und dann gibt es natürlich noch weitere Dinge, die beachtet werden müssen: Businesslogik, Business Rules usw.

    • Beitragspunkte: 20
    • IP-Adresse ist Registriert
  • 08-25-2008 8:20 Antwort zu

    AW: Konzept zur erstellung einer neuen Software

    Es soll möglich sein Änderungen/Erweiterungen zur Laufzeit vorzunehmen. Wenn der Kunde eine neue Entität und damit auch weitere Tabellenspalten (oder vielleicht sogar eine neue Tabelle) erstellt sollen diese Änderungen in der Datenbank liegen.
    Ich habe gerade mal über die Webseite von StringTemplate drüber geschaut. Da die Engine selbst in Java ist kommt das Projekt für uns vermutlich nicht in Frage da wir eine Engine brauchen die unsere Anforderungen (die sehr umfangreich sind) erfüllen muss.

    Hast du zufällig ein paar interessante Artikel über die Patterns? Ich werde mich mal damit beschäftigen.

    • Beitragspunkte: 20
    • IP-Adresse ist Registriert
  • 08-25-2008 9:54 Antwort zu

    • Norbert Eder
    • Top 10 Mitwirkender
      Männlich
    • Registriert am 04-09-2008
    • Graz / Austria
    • Beiträge 502
    • Punkte 7.469
    • ForumsAdministrator

    AW: Konzept zur erstellung einer neuen Software

    Die String Templates gibt es auch für .NET.

    Du kannst deine Typ-Informationen natürlich in einer Datenbank ablegen. Kein Problem. Mit diesen Informationen kannst du zwei Dinge recht einfach machen:

    • Den Typen zur Laufzeit erstellen (siehe Beispiel unten)
    • Bei der Ablage der Typinformationen die entsprechende Maske generieren

    Damit solltest du alles recht einfach erledigen können. Hier noch ein Beispiel, wie du auf Basis der gesammelten Informationen Typen zur Laufzeit erstellen kannst:

    namespace DotNetGui.DynamicObjects
    {
        public class ObjectCreator
        {
            public static ObjectCreator _instance;
            public static object _lockObject = new object();
    
            public static ObjectCreator Instance
            {
                get
                {
                    lock (_lockObject)
                    {
                        if (_instance == null)
                            _instance = new ObjectCreator();
                    }
                    return _instance;
                }
            }
    
            public object CreateObject(Type type, Dictionary<string, object> values) 
            {
                object obj = Activator.CreateInstance(type);
                if (obj != null)
                {
                    PropertyInfo[ propInfos = type.GetProperties();
                    foreach (PropertyInfo pi in propInfos)
                    {
                        if (values.ContainsKey(pi.Name))
                        {
                            pi.SetValue(obj, values[pi.Name], null);
                        }
                    }
                    return obj;
                }
                return null;
            }
    
            public Type CreateType(string typeName, Collection<PropertyDescriptor> properties)
            {
                if (String.IsNullOrEmpty(typeName))
                    throw new ArgumentException("typeName must not be null or empty");
    
                if (properties == null || properties.Count == 0)
                    throw new ArgumentException("No properties given");
    
                AssemblyName assemblyName = new AssemblyName();
                assemblyName.Name = "temporaryAssembly";
                AssemblyBuilder assemblyBuilder = Thread.GetDomain().DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
                ModuleBuilder module = assemblyBuilder.DefineDynamicModule("temporaryModule");
    
                TypeBuilder typeBuilder = module.DefineType(typeName, TypeAttributes.Public | TypeAttributes.Class);
    
                MethodAttributes methAttributes = MethodAttributes.Public | MethodAttributes.HideBySig;
    
                foreach (PropertyDescriptor desc in properties) 
                {
                    FieldBuilder field = typeBuilder.DefineField("_" + desc.PropertyName, desc.PropertyType, FieldAttributes.Private);
                    PropertyBuilder property = typeBuilder.DefineProperty(desc.PropertyName, desc.PropertyAttributes, desc.PropertyType, new Type[ { desc.PropertyType });
    
                    MethodBuilder getPropBuilder = typeBuilder.DefineMethod("get_value", methAttributes, desc.PropertyType, Type.EmptyTypes);
                    MethodBuilder setPropBuilder = typeBuilder.DefineMethod("set_value", methAttributes, null, new Type[ { desc.PropertyType });
    
                    ILGenerator getIL = getPropBuilder.GetILGenerator();
                    getIL.Emit(OpCodes.Ldarg_0);
                    getIL.Emit(OpCodes.Ldfld, field);
                    getIL.Emit(OpCodes.Ret);
                    ILGenerator setIL = setPropBuilder.GetILGenerator();
                    setIL.Emit(OpCodes.Ldarg_0);
                    setIL.Emit(OpCodes.Ldarg_1);
                    setIL.Emit(OpCodes.Stfld, field);
                    setIL.Emit(OpCodes.Ret);
    
                    property.SetGetMethod(getPropBuilder);
                    property.SetSetMethod(setPropBuilder);
                }
    
                return typeBuilder.CreateType();
            }
        }
    }

    Darin enthalten sind zwei Methoden. Die eine erstellt den Typen, die andere bietet die Möglichkeit, einen beliebigen Typen mit Werten zu befüllen. Hier  nun, wie das verwendet werden kann:

    namespace DotNetGui.DynamicObjects
    {
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
    
                Collection<PropertyDescriptor> props = new Collection<PropertyDescriptor>();
                PropertyDescriptor prpDescFirstName = new PropertyDescriptor();
                prpDescFirstName.PropertyName = "FirstName";
                prpDescFirstName.PropertyType = typeof(String);
                prpDescFirstName.PropertyAttributes = System.Reflection.PropertyAttributes.None;
                props.Add(prpDescFirstName);
                PropertyDescriptor prpDescLastName = new PropertyDescriptor();
                prpDescLastName.PropertyName = "LastName";
                prpDescLastName.PropertyType = typeof(String);
                prpDescLastName.PropertyAttributes = System.Reflection.PropertyAttributes.None;
                props.Add(prpDescLastName);
    
                Type t = ObjectCreator.Instance.CreateType("Person", props);
                Dictionary<string, object> valueDict = new Dictionary<string, object>();
                valueDict.Add("FirstName", "Norbert");
                valueDict.Add("LastName", "Eder");
                Object obj = ObjectCreator.Instance.CreateObject(t, valueDict);
    
                this.DataContext = obj;
            }
        }
    }

    Und dazu passend noch das XAML für das Fenster. Hier fehlt für dich dann noch das Generieren der Page + das Laden derselben:

    <Window x:Class="DotNetGui.DynamicObjects.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Dynamic Objects Demo" Height="300" Width="300">
        <StackPanel>
            <TextBlock Text="FirstName"/>
            <TextBox x:Name="FirstNameBox" Text="{Binding Path=.FirstName}"/>
            <TextBlock Text="LastName"/>
            <TextBox x:Name="LastNameBox" Text="{Binding Path=.LastName}"/>
        </StackPanel>
    </Window>

    Ich hoffe, das hilft dir mal soweit weiter.

    • Beitragspunkte: 5
    • IP-Adresse ist Registriert
Seite 1 von 1 (4 Treffer)
Powered by Community Server (Commercial Edition)    Hosting powered by 69° media solutions