Peter Bucher - Mein Experiment, meine Spielereien, meine Welt...   ·   Stefan Falz   ·   Jürgen Gutsch   ·   Golo Roden   ·   ASP.NET Zone   ·   Microsoft ASP.NET
Willkommen bei ASP.NET Zone. Anmelden | Registrieren | Hilfe

CSS: Vertikaler Scrollbalken erzwingen

Bei Webseiten die nicht über die Höhe des Browsers (Viewports) hinausgehen, also relativ wenig Inhalt haben, gibt es beim Wechsel zu einer Seite die darüber hinausgeht ein horizontales verschieben der Seite.

Das Problem entsteht, weil z.B. Firefox / Chrome den vertikalen Scrollbalken bei nicht ausreichendem vertikalem Inhalt weglassen.
Der Internetexplorer hat dieses Problem nicht und zeigt das meines Erachtens korrekte Verhalten: Er zeigt den vertikalen Scrollbalken immer an.

Um dieses korrektere Verhalten in allen Browsern zu erzwingen gibt es verschiedene Lösungen.

Die nicht valide Lösung, die inzwischen in jedem aktuellen Browser laufen sollte:

html {
    overflow-y: scroll;
}

 

 

Oder die valide Lösung, die auch in älteren Browsern läuft, jedoch durch das 1% erzwungene mehr an Höhe, diese etwa 10 Pixel unten auch an die sonst leere Seite anhängt:

html {
    height: 100%;
}
body {
    height: 101%;
}

 

 

Alternativ dazu sollte auch folgendes funktionieren:

html {
    height: 100%;
    margin-top: 1px;
}

Habt ihr andere Lösungen oder Kommentare zu diesen hier? Schreibt in die Kommentare.

Eingetragen von Peter Bucher | 0 Kommentare
Abgelegt unter: , , ,

IE: neu geöffnetes Tab bleibt leer, obwohl Einstellung geändert

Darauf muss man zuerst kommen: Die Toolbar des Antiviren Programms "Free AVG" verpfuscht die Internet Explorer Einstellungen.

Das wirkt sich so aus, dass nach jedem Neustart und obwohl schön neu eingestellt, beim öffnen eines neuen Tabs nur eine leere Seite kommt.
Und nicht wie gewünscht die erste Startseite als neues Tab.

Der Übeltäter kann entweder auf die angenehme oder auf die harte Tour entfernt werden.
Nachdem entfernen einmal das gewünschte einstellen und es bleibt auch.

Quelle: http://answers.microsoft.com/en-us/ie/forum/ie9-windows_vista/new-tab-page-on-internet-explorer-keeps-changing/6dd63d7a-1181-4ffb-a256-225ba5a528e1

Eingetragen von Peter Bucher | 0 Kommentare
Abgelegt unter: , , , , ,

LightCore 1.5.1 Release

Es wurde soeben die Version 1.5.1 von LightCore veröffentlicht.

LightCore ist auf Constructor Injection optimiert. In der Version 1.5 hat sich leider ein Fehler eingeschlichen.
Die PropertyInjection wurde bei jeder Typenauflösung ausgeführt. Dies führte zu einer StackOverlow-Exception wenn eine zirkuläre Abhängigkeit, z.B. View.Presenter / Presenter.View vorhanden ist.

Da LightCore zirkuläre Abhängigkeiten nicht unterstützt wird, wurde die automatische PropertyInjection entfernt. So sollten keine Fehler mehr auftreten und das PropertyInjection ist optional.

Das aktuelle Release findet sich unter http://lightcore.ch/

Ich entschuldige mich für die Unanehmlichkeiten und wünsche viel Erfolg.

Eingetragen von Peter Bucher | 0 Kommentare

Gastbeitrag: MVP oder MVVM? Was gehoert wohin?

Einleitung

Ein Kollege von mir hat sich intensiv mit den Designpatterns MVP und MVVM auseinandergesetzt und unter anderem auch mit mir diskutiert.
Da ich seine Gedanken sehr interessant fand, kam uns schlussendlich die Idee, diese als Gastbeitrag in meinem Blog zu veröffentlichen.
Der Hauptgedanke dieser Veröffentlichung ist Entwirrung und das Einholen von Feedback zu diesem Thema aus meiner Leserschaft.

In diesem Sinne wünsche ich euch viel Spass mit dem Gastbeitrag und wir freuen uns auf reichliches Feedback.

Gastbeitrag

Die Designpatterns MVP (Model - View - Presenter) und MVVM (Model - View - ViewModel) sind Designpatterns für die Strukturierung und Trennung von Daten, Ansicht und Presentationslogik.
Ich habe mich im Zusammenhang mit der Entwicklung eines Applikationsframework für Businessanwendungen damit beschäftigt und schaute dazu im Internet verschiedene Implementierungen und Blogeinträge an. Mein Verständnis hatte sich dabei nicht vergrössert, sondern erstmal mehr Verwirrung geschaffen:

  • Was ist der Unterschied zwischen einem Model und einem Entity?
  • Was ist ein Presenter?
  • Was ist Presentationslogik?
  • Was ist der Unterschied zwischen Presenter und ViewModel?

Ich versuche möglichst knapp meine Ansicht mitzuteilen und auch Beispiel-Code anzubieten. Im folgenden Beispiel verwende ich das MVP-Pattern:

Entity / Model:

Ein Entity enthält Daten wie Name, Adresse und Ort usw. z.B. eines Customers:

 


public class CustomerEntity
    {
        public int CustomerId { get; set; }

        public string Name { get; set; }

        public string Address { get; set; }

        public string Location { get; set; }
    }

 

Ein Model enthält wiederum ein oder mehrere Entities (z.B. ein zu editierender Customer oder ein Suchergebnis).

Das Model stellt die dazugehörenden Methoden, um Entities zu laden, zu suchen oder abzuspeichern zur Verfügung.
Zusätzlich darf im Model der Status des Views gespeichert werden, z.B. IsCustomerSelected, um gebunden mit der Eigenschaft IsEnabled eines Button zu unterscheiden, ob ein Customer im ListView der Ansicht selektiert wurde und somit editiert werden kann oder nicht.
Eigenschaften wie die eines Customers sollten meiner Meinung nach nicht im Model zur Verfügung gestellt werden, sondern getrennt in einem separaten Entity, obwohl dies in den meisten Artikel bezüglich MVP / MVVM genau anders dargestellt wird.
Im MVVM-Pattern wird von Microsoft empfohlen, die Daten sogar im ViewModel (Presenter) einzufügen; diese Mischung zwischen einerseits Daten und Presentationslogik steht die Möglichkeit entgegen, ableitbare Model-BasisKlassen für Daten und Basisklassen für Presentationslogik zu entwickeln.

In der Basisklasse für Modelle sollte INotifyPropertyChanged implementiert werden, damit die Ansicht, falls mit DataBinding gearbeitet, aktualisiert wird.

 


public class Model : INotifyPropertyChanged
    {
        public void OnPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }

public class EditCustomerModel : Model
    {
        private CustomerEntity _customer;

        public void NewCustomer()
        {
            this.Customer = new CustomerEntity();
        }

        public void EditCustomer(int customerId)
        {
            // Code, um Customer Entity zu laden
            // this.Customer = ...
        }

        public CustomerEntity Customer
        {
            get { return _customer; }
            set
            {
                _customer = value;

                this.OnPropertyChanged("Customer");
            }
        }
    }

public class SearchCustomerModel : Model
    {
        private IEnumerable<CustomerEntity> _customers =
new List<CustomerEntity>();

        private CustomerEntity _selectedCustomer = null;

        public CustomerEntity SelectedCustomer
        {
            get { return _selectedCustomer; }
            set
            {
                _selectedCustomer = value;

                // Aktualisiert DataBindings für SelectedCustomer
                this.OnPropertyChanged("SelectedCustomer");

                // Aktualisiert die IsEnabled Eigenschaft des Buttons
                this.OnPropertyChanged("IsCustomerSelected");
            }
        }

        public IEnumerable<CustomerEntity> Customers
        {
            get { return _customers; }
            set
            {
                _customers = value;

                // OnPropertyChanged aktiviert das updaten der Liste in der Ansicht, falls DataBinding verwendet wurde
                this.OnPropertyChanged("Customers");
            }
        }

        public void LoadAllCustomers()
        {
            // Code, um alle CustomerEntities zu laden
            // this.Customers = ...
        }

        public void SearchCustomers(string text)
        {
            // Code, um CustomerEntities zu laden
        }

        public bool IsCustomerSelected
        {
            get
            {
                return this.SelectedCustomer != null ? true : false;
            }
        }
    }

 

 

View:

Die Views hier als Code bereitzustellen, sprengt den Rahmen dieses Artikels. Ich bitte hierzu die Vorstellungskraft des Lesers zu bemühen, um sich die Views für EditCustomerView und SearchCustomerView vorzustellen.
Das Databinding für ListView und SearchCustomerModel.Customers, sowie den Edit Button mit IsCustomerSelected zu verknüpfen, können wir uns vorstellen.
Im View ist eine Referenz auf den Presenter zu setzen, um auf die Methoden des Presenters zugreifen zu können.

 


public partial class SearchCustomerView : Page
    {
        private SearchCustomerPresenter Presenter { get; set; }

        public SearchCustomerView()
        {
            InitializeComponent();

            // Neue Presenter Instanz
            this.Presenter = new SearchCustomerPresenter();

            // Model binden mit DataContext des View für DataBinding
            this.DataContext = this.Presenter.Model;

        }

        private void searchButton_Click_1(object sender, RoutedEventArgs e)
        {
            this.Presenter.SearchCustomers(this.searchTextBox.Text);
        }

        private void loadAllCustomers_Click_1(object sender, RoutedEventArgs e)
        {
            this.Presenter.LoadAllCustomers();
        }
    }

 

Presenter / ViewModel:

Persönlich finde ich die Namensgebung Presenter besser als ViewModel; so kann besser zwischen Model-, View- und Presenterklassen unterschieden werden.
Im Presenter ist die Presentationslogik. Der Presenter delegiert meistens nur vom View zum Model.
Microsoft empfiehlt bezüglich MVVM das ViewModel (Presenter) als DataContext im View zu setzen - dies im Zusammenhang mit Commands, die sich im Presenter befinden und mit Steuerelementen des Views gebunden werden; in meinem Beispiel setze ich als DataContext das Model.

Ich meine, dass das MVVM Schema im Sinne von Microsoft hinterfragt werden muss, denn Microsoft trennt im MVVM-Schema nicht klar zwischen Model und Presenter oder besser ausgedrückt zwischen Daten und Presentation. Das Model klar vom ViewModel (Presenter) zu trennen, ist ja aber gerade die ursprüngliche Idee dieser Pattern MVP und MVVM.

Meiner Ansicht nach gehören Daten ins Model und nicht in die Presentationslogik: deshalb setze ich das Model als DataContext im View und nicht das ViewModel (Presenter).

In meinem Beispiel habe ich eine einfache Implementierung verwendet, ohne Kommunikation zwischen Presenter und View:

 


public class EditCustomerPresenter
    {
        public EditCustomerPresenter()
        {
            this.Model = new EditCustomerModel();
        }

        public void NewCustomer()
        {
            this.Model.NewCustomer();
        }

        public void EditCustomer(int customerId)
        {
            this.Model.EditCustomer(customerId);

            // Falls ohne DataBinding per xaml:
            // UpdateView();
        }

        public EditCustomerModel Model { get; set; }
    }

public class SearchCustomerPresenter
    {
        public SearchCustomerPresenter()
        {
            this.Model = new SearchCustomerModel();
        }

        public SearchCustomerModel Model { get; set; }

        public void SearchCustomers(string text)
        {
            this.Model.SearchCustomers(text);
        }

        public void LoadAllCustomers()
        {
            this.Model.LoadAllCustomers();
        }
    }

 

Um nun an einem ganz kleinen Beispiel zu veranschaulichen, was Presentationslogik ist, erweitere ich die SearchCustomers Methode etwas:

 


public void SearchCustomers(string text)
        {
            this.Model.SearchCustomers(text);
               
MessageBox.Show(String.Format("{0} Kunde(n) gefunden.", this.Model.Customers.Count()));
           
        }

 

Wo sonst sollte die MessageBox die Anzahl der Ergebnisse anzeigen, wenn nicht in der Presentationslogik des Presenters? Diese Info soll natürlich nur die Presenationslogik veranschaulichen; solche unnötigen Infos sollten in Businessapplikationen vermieden werden.

Auch erfahrene Entwickler brauchen etwas Zeit, wenn sie sich zum ersten Mal mit MVP und MVVM beschäftigen, um diese Patterns zu verstehen. Das beste Verständnis habe ich persönlich beim Implementieren eigener MVPs gewonnen und kann das nur weiterempfehlen.

Hier eine fragwürdige Implementierung des MVVM:

http://msdn.microsoft.com/de-de/magazine/dd419663.aspx

Hierzu einige Äusserungen:
Erstmal vorne weg: In diesem Artikel scheint ein Model gar nicht erst vorzukommen; die Daten wurden in das ViewModel, bzw. in den Presenter, also in die Presentationlogik hineingesetzt. Deshalb wurde dort auch die Schnittstelle INotifyPropertyChanged implementiert, die klar ins Model gehört.


Fazit:
 
Der MVP Pattern trennt klar Model und Presenter; der MVVM Pattern scheint diese Trennung nicht mehr anzustreben. Auch wenn wir uns vorstellen, Models zu entwickeln, die mit Hilfe von Generics standardmässig Eigenschaften zur Verfügung stellen, scheint mir die Trennung zwischen Model und Presenter im Sinne der Klassenhierarchie wichtig; So würden wir wohl Basisklassen einerseits für Daten-Modelle und andererseits für Presentationslogik erstellen und kaum beides in eine ViewModel-Klasse zwängen.
Wichtig ist für mich auch die Trennung zwischen Entity und Model.
Der MVVM Pattern scheint einige sinnvolle Eigenheiten des MVP Pattern über Bord zu schmeissen (z.B. klare Trennung zwischen Model und Presenter). Die aufwendige Verwendung von Commands sehe ich nicht als existentielle Erweiterung beim MVVM; ich sehe die MVP Implementierung als einfacher und klarer an.


Stefan Werdenberg, IntegralFramework

LightCore 1.5 Release

Die Version 1.5 von LightCore wurde eben veröffentlicht.

Folgend ein Auszug aus dem Changelog:

  • OpenGeneric to ClosedImplementation is now possibile to use with XML (e.g.
    IRepository{1}, FooRepository).
    - Extended Generic Syntax in XML, with Alias Support for generic Arguments like Unity does.
  • Bugfixes:
    Fixed ResolveAll throws InvalidOperationException bug.
    see: (http://www.mycsharp.de/wbb2/thread.php?threadid=87886).
  • Fixed ThreadSingleton does not release references after thread exit bug.
    see: (http://www.mycsharp.de/wbb2/thread.php?threadid=87567&hilight=lightcore).
  • Fixed ReflectionActivator uses non public constructors bug.
    see: (http://www.mycsharp.de/wbb2/thread.php?threadid=87839).
  • Fixed LazyRegistrationSource does not assign ContractType property.
  • Fixed Direct type comparison makes a given concrete type as a constructor argument invalid.
    Solution: Instead of type == type, usage of type.IsAssignable(type).
  • Fixed: Invalid reuse of previous cached arguments (caching of runtime arguments are now disabled).
  • Fixed: DefaultScope which was altered by code, is working with all kinds of
    activators. And autonome activators working regardless this DefaultScope.
  • Fixed: RegistrationSources (generic ones, Func<T>, Lazy<T>, ...
  • Fixed: Made RegistrationContainer threadsafe.


LightCore ist unter http://lightcore.ch/ erreichbar.

 

Was kostet LightCore?

Die Binaries von LightCore dürfen in jeglicher Art von Projekten (privat, kommerziell, ...) kostenlos genutzt werden.
Der Quellcode von LightCore steht unter der MS-PL-Lizenz.

Eingetragen von Peter Bucher | 2 Kommentare
Abgelegt unter: , ,

Metro style Apps mit xunit testen

Gerade habe ich eine Classlibrary in eine Metro-Solution hinzugefügt und wollte die Referenz auf NUnit hinzufügen um Unittests zu erstellen.
Leider habe ich schlecht gestaunt dass das mit NUnit nicht mehr geht, es ist einfach zu alt und es gibt noch nichts von NUnit das läuft, meines Wissens.

Ich bin dann auf folgenden Blogeintrag gestossen, wo xunit benutzt wird, davon gibt es ein Kompilat das sich einbinden lässt.

Ganz einfach zwei Extensions für VS2012 installieren, neustarten und das Projekttemplate - wie im Blogpost erklärt - erstellen.

Und los gehts!

Eingetragen von Peter Bucher | 0 Kommentare
Abgelegt unter: , , , ,

Paypal Spenden Button in ASP.NET einfügen

Ich wollte einen Paypal Spenden Button auf der LightCore Seite einzufügen, doch ein Button mit komplettem Formular-Tag das von Paypal geliefert wird ist schlecht zu nutzen.
In einen Blog fand ich ein Beispiel, wie ein Spenden Button per Link eingefügt werden kann, per GET also.

Zuerst muss ein Button bei Paypal erstellt werden, damit die ID des Buttons verfügbar ist.

Im folgenden Code dann nur noch die ID des Buttons durch die von Paypal ersetzen èt voila.

<a target="_blank" href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=ButtonIDHierErsetzen">Spende an Produkt XYZ</a>

Kurz und schmerzlos, vielleicht kann es jemand gebrauchen.

Eingetragen von Peter Bucher | 0 Kommentare
Abgelegt unter: , , , ,

Solution Dateien als Administrator öffnen

Was unter Windows 7  nicht der Fall war, ist bei Windows 8 jetzt der Fall.

Verknüpfungen auf Visual Studio Solution Dateien (*.sln) können nicht per Rechtsklick oder über die Eigentschaften des Links als Administrator gestartet werden.

Das ist mühsam. Bei einem ASP.NET Projekt kommt ohne Adminstratorrechte immer Fehler und immer nur das leere VS öffnen ist auch doof.

Nach einer zweiten Suche - Gestern habe ich nichts gefunden - fand ich die Lösung bei David.

Eine Registry-Datei, bspw. RunAsAdministrator.reg mit folgendem Inhalt als Textdatei erstellen:

Windows Registry Editor Version 5.00
 
[HKEY_CLASSES_ROOT\VisualStudio.Launcher.sln\Shell\runas\Command]
@="\"C:\\Program Files (x86)\\Common Files\\Microsoft Shared\\MSEnv\\VSLauncher.exe\" \"%1\""


Der Pfad "Program Files (x86))" muss gegebenfalls angepasst werden.
Für ein Englisches Windows 64Bit passt es.

Nach dem Ausführen der Datei ist die Option per Rechtsklick und auch in den Einstellungen der Verknüpfung verfügbar.
Mit letzerem ist es möglich, die Verknüpfung normal zu öffnen - es wird immer als Administrator ausgeführt.

Ich hoffe das hilft einigen hier draussen.

Da war doch noch was: Windows 8

Mit Windows 7 bin ich schon länger sehr zufrieden und habe lange gewartet.
Seit kurzem habe ich Windows 8 und möchte ein wenig berichten, was ich denn darüber denke.

Die Installation verlief eigentlich relativ glimpflich und relativ schnell. Hatte nur Startschwierigkeiten mit meinem USB-Stick.

Kein Startmenü geht für mich gar nicht, tut mir leid.
Es ist einfach zu praktisch mit der Windows-Taste automatisch etwas auszuführen oder zu starten, wenn man es eintippt.
Und auch sonst ist man sich das gewohnt.

Nach kurzer Suche sties ich auf das Programm Start8. Ja ich weiss, es gibt auch kostenlose Alternativen, aber die 5$ haben mich nicht geschmerzt dafür. Es wird ein gutes Programm abgeliefert.

Das Startmenü ist wie in Windows 7 und kann sogar noch Verändert werden.
Dazu lässt sich im Programm einstellen, dass Windows mit dem Desktop startet, nicht mit dem Windows 8 Startbildschirm.

Etwas nerviges ist dann noch der Spellchecker im Internet Explorer, bzw. global.
Der kann so ausgeschalten werden.

Im Firefox kann der Spellchecker so ausgeschalten werden.


Was gibts noch zu sagen. Von der Geschwindigkeit her verglichen mit Windows 7 eher schneller. Aber das kann auch daran liegen, dass die vorherige Installation einfach schon alt war.

Das Einfenster-System von Windows 8 für Desktop geht für mich einfach gar nicht und der Desktop als so eine Krücke ohne Startmenü.

Auf einem Tablet oder so geht es vielleicht ja noch, aber für Desktop muss ein Mehrfenster-System her und zwar standardmässig.

Im kopieren / verschieben, etc. von Dateien und Ordnern ist Windows auch nicht besser geworden.

Aber was gib es schon für Alternativen?
Man lebt halt mit den Schwächen und geniesst die Annehmlichkeiten.

Was ist eure Erfahrung mit Windows 8?
Eingetragen von Peter Bucher | 2 Kommentare
Abgelegt unter: , ,

Hartnäckige Fehlern mit minimalem Nachbau auf die Schliche kommen

Es gibt sie überall und immer wieder: Hartnäckige Fehler, die einfach nicht zu finden sind.
Wer schon seit geraumer Zeit vor einem Fehler sitzt und wirklich schon alles versucht hat, muss sich eine Alternative überlegen.

Die Lösung ist häufig ein minimales Testprojekt zu erstellen und dort alles nachzubauen, um das Problem zu reproduzieren.
Das minimale Testprojekt kann eine Kopie es Originals sein, das einfach abgespeckt wird, oder eine Nachstellung in einem neuen Projekt.

So viel Aufwand ist das meistens nicht und häufig werden "doofe" Fehler während dem Erstellen gefunden.

Kann der Fehler reproduziert werden, wird weiter abgespeckt, bis es funktioniert.
Danach muss der Unterschied zwischen dem Original und dem Testprojekt gefunden werden.
Es kann auch wieder Code vom originalen Projekt eingefügt werden, um so den Ort des Fehlers einzugrenzen.

In den meisten Fällen kann so ein Fehler aufgespürt werden.

Eine Alternative dazu ist das kommentieren von Code, bis es funktioniert.
Aber ein Neubau oder Abbau von Code wie oben beschrieben ist der übersichtlichere Weg, finde ich.

Eingetragen von Peter Bucher | 1 Kommentare

Teil 2: Umkehrung der Kontrolle erkärt, oder: Von der Fabrikmethode zum DI-Container

Dies ist die Fortsetzung der Artikelserie "Umkehrung der Kontrolle erkärt, oder: Von der Fabrikmethode zum DI-Container" mit folgenden Teilen:

Der erste Teil liegt schon eine Zeit zurück, das hindert mich aber nicht daran, da doch noch mehr zu veröffentlichen.

Ein Rückblick auf Teil 1:

Wir haben Abhängigkeiten angeschaut, worin die Probleme liegen wie sie mithilfe der Umkehrung der Kontrolle mittels Factory Methode umgangen werden können.

Es gibt noch das Abstract Factory Pattern, von der Gang of Four folgendermassen beschrieben:

Bietet eine Schnittstelle zum Erzeugen von Familien verwandter oder voneinander abhängiger Objekte, ohne ihre konkreten Klassen zu benennen.

Auf folgender Abbildung ist gut zu erkennen, was für Akteure mitspielen:

  • Eine Schnittstelle Abstract Factory, die nur die Interfaces der Produkte zurückgibt.
  • N konkrete Implementationen wie z.B. Concrete Factory A.
  • Implementationen von den Produkten

Dieses Pattern erinnert mich an das Provider Pattern, wo es einen abstrakten Provider und bspw. FileProvider und SqlProvider gibt.
Einfach das in diesem Fall hier Objekte in verschiedenen Familien erzeugt werden, anstelle ein Verhalten in verschiedenen Familien zu repräsentieren.

Ich habe es in dieser Form noch nie genutzt aber es gibt sicher Einsatzfälle und Abwandlungen davon.

Das war jetzt ein kleiner Ausflug in die Patterns, aber eigentlich ging es darum, den Weg von der Fabrikmethode zum DI-Container zu beschreiben.

Eine Fabrikmethode ist das Mittel des DI-Containers, der dafür gedacht ist das schreiben und verwalten von vielen Factorymethoden zu ersparen. Er stellt eine globale Factorymethode dar, die über den Interfacetyp eine konkrete Klasse zurückgibt, die im Container registriert ist.

Er geht noch weiter indem er ganze Objekthierarchien von Abhängigkeiten in Form von Konstruktorargumenten oder Eigenschaften auflösen kann.

Diese gewonnene Bequemlichkeit forciert auch das Unterteilen von Code in mehrere Klassen, die jeweils dedizierte Aufgaben haben und dann per Container injiziert werden können.

 

Ich habe länger überlegt, was ich noch in diesen Artikel bringen soll. Es gibt sehr viele kleine, simple, einfache Beispiele für einen Container.
Zum Abschluss gibt es noch den Quellcode des Vorgängers von LightCore, der schon einiges konnte aber viel viel kleiner war als die aktuelle Version von LightCore.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using PeterBucher.AutoFunc.Fluent;
using PeterBucher.AutoFunc.Mapping;
namespace PeterBucher.AutoFunc
{
    public class AutoFuncContainer : IContainer
    {
        private readonly IDictionary<Type, IMappingItem> _mappings;
 
        public AutoFuncContainer()
        {
            this._mappings = new Dictionary<Type, IMappingItem>();
        }
 
        public ILifecycleFluent Register<TContract, TImplementation>()
        {
            Type typeOfContract = typeof (TContract);
            MappingItem mappingItem;
 
            if (!this._mappings.ContainsKey(typeOfContract))
            {
                Type typeofImplementation = typeof (TImplementation);
                mappingItem = new MappingItem(typeofImplementation);
                this._mappings.Add(typeOfContract, mappingItem);
                return mappingItem.LifecycleFluent;
            }
 
            throw new Exception("mapping for this contract allready registered");
        }
 
        private object Resolve(Type typeOfContract)
        {
            IMappingItem mappingItem = _mappings.Where(m => m.Key.Equals(typeOfContract)).SingleOrDefault().Value;
 
            switch (mappingItem.Lifecycle)
            {
                case Lifecycle.Singleton:
                    if (mappingItem.Instance == null)
                    {
                        this.CreateInstanceFromType(mappingItem.ImplementationType);
                    }
                    return mappingItem.Instance;
            }
 
            return this.CreateInstanceFromType(mappingItem.ImplementationType);
        }
 
        public TContract Resolve<TContract>()
        {
            return (TContract) this.Resolve(typeof (TContract));
        }
 
        private object CreateInstanceFromType(Type implementationType)
        {
            ConstructorInfo[] constructors = implementationType.GetConstructors();
            if (constructors.Length == 0 || constructors.Length == 1 && constructors[0].GetParameters() == null)
            {
                return Activator.CreateInstance(implementationType);
            }
 
            ConstructorInfo constructorWithDependencies = constructors.OrderByDescending(
                delegate(ConstructorInfo c)
                    {
                        var parameters = c.GetParameters();
                        return parameters == null || parameters.Count() == 0;
                    }).First();
 
            List<object> parameterResults = new List<object>();
 
            foreach (var parameter in constructorWithDependencies.GetParameters())
            {
                parameterResults.Add(this.Resolve(parameter.ParameterType));
            }
 
            return constructorWithDependencies.Invoke(parameterResults.ToArray());
        }
    }
}

Eingetragen von Peter Bucher | 2 Kommentare
Abgelegt unter: , , , ,

Feedbackmöglichkeit zu LightCore

Ich möchte in einiger Zeit LightCore 1.5 veröffentlichen, darin enthalten sind unter anderem einige Bugfixes.

Ausserdem möchte ich aber die Zeit noch nutzen, evt. das eine oder andere umzubauen und möchte eure Meinung berücksichtigen.

 

Damit ihr die Möglichkeit habt vor dem Release noch ein Vorschlag zu machen, gibt es jetzt die Seite https://lightcore.uservoice.com/.
Auf der http://lightcore.ch/ ist UserVoice über ein Widget erreichbar.

 

Ich hoffe auf einige interessante Vorschläge!

Eingetragen von Peter Bucher | 0 Kommentare
Abgelegt unter: , ,

Aussehen von VS2012 an VS2010 anpassen

Allen denen es gleich geht wie mir und nicht so viel mit der neuen Oberfläche von Visual Studio 2012 anfangen können finden zumindest eine teilweise Lösung.

Zuerst das Endergebnis: VS2012 in neuem Look

1. Für ein anderes Farbschema gibt es den Visual Studio 2012 Color Theme Editor.
Blau entspricht dabei in etwa den Farben von Visual Studio 2010.

2. Und für die Icons, die nach meinem Geschmack sehr trist daherkommen...

  => 

...gibt es den Visual Studio Icon Patcher.

Thomas Schissler hat mein Blogpost aufgegriffen und hat noch ein Tipp bekommen, um Menuicons zu tauschen.

3. Dies lässt sich mit NiceVS bewerkstelligen.

Hier nochmals die Links zu allen Tools:

Eingetragen von Peter Bucher | 0 Kommentare
Abgelegt unter: , ,

See# Party 2011 am Bodensee

Die vom .NET-Stammtisch Konstanz-Kreuzlingen (DE / CH) veranstaltete .NET Community Konferenz mit dem Namen See# Party geht in die zweite Runde. 

 

Die Rückmeldungen und Stimmen aus der ganzen .NET Community von Deutschland und der Schweiz von der ersten Veranstaltung im letzten Jahr waren so positiv, das die Usergroup gestützt durch einen Schweizer-Verein (Usergroup), eine zweite Konferenz geplant hat, die dieses Jahr am 20. August stattfindet.

- Rückblick in Form von Bildern und Blogpost-Feedback zur See# Party 2010 um einen Eindruck zu bekommen

Für ganz frühe Frühbucher gehts hier lang!

Die Agenda mitsamt ihren Sprechern und Themen sollte für jeden von euch etwas beinhalten. (Der Inhalt kann sich noch ändern, dies ist eine Kopie. (Hier gehts zum Original).
Ich habe die aus meiner Sicht herausstechenden Themen hervorgehoben.


Zeit Track 1
Web
Track 2
Mobile
Track 3
Desktop
Track 4
Cloud
08:30 Einlass
09:00 Begrüßung:
(Jürgen Gutsch, Tilo Schinke, Golo Roden)
09:15 Keynote: Eine Branche im Wandel?
(Laurin Stoll)
10:00 Pause
10:15 Sponsor Session
ASP.NET MVC 3
(Microsoft Schweiz)
Phone 7 - Did they save us from our phones?
(David Tielke)
XAML Deep Dive
(Mathias Raacke)
Cloud, On-Premise & Co – was für wen?
(Golo Roden)
11:15 Pause
11:45 SharePoint
(Thorsten Hans)
Sponsor Session
Caché
(InterSystems)
WCF 4.0 - Die Neuerungen
(David Tielke)
Die Microsoft Cloud - wolkig mit Sonnenschein
(Robert Eichenseer)
12:45 Mittagspause
13:45 Agil 2.0 - Das Agile Developement Framework
(Golo Roden)
The Pragmatic Entrepreneur
(Laurin Stoll)
Accessibility - Digitale Barrieren und wen wir damit aussperren
(Jürgen Gutsch)
SOS: Optimizing the Wire
(Hannes Preishuber)
14:45 Pause
15:15 User Interface Patterns in Silverlight
(Roland Weigelt)
WP7 Jumpstart - von 0 auf App!
(Karsten Samaschke)
Sponsor Session
PostSharp
(SharpCrafters)
Wer bin ich? - Von Active Directory zu einer Windows Azure Application
(Robert Eichenseer)
16:15 Pause
16:45 ASP.NET Dynamic Data
(Mathias Raacke)
Windows Phone 7 - Developer Tools & Toolkits
(Patrick Getzmann)
Workflow Foundation 4 - Getting Started
(Boas Enkler)
Sponsor Session
List&Label
(combit GmbH)
17:45 Pause
18:00 Große Verlosung und Abschlussveranstaltung
(Jürgen Gutsch, Tilo Schinke, Golo Roden)


Weitere, nähere Infos gibt es unter dem Blogpost von Jürgen Gutsch zur See# Party 2011 oder auf der offiziellen Seite.

Wir sehen uns dort, zur vorzeitigen Anmeldung mit Frühbucherrabatt gehts hier lang.

Eingetragen von Peter Bucher | 1 Kommentare

Das neue Projekt der "zwei" - http://www.xmlrepository.ch/

Golo Roden und meine Wenigkeit haben sich seit langem wieder eine Auszeit aus der stressigen Realität gegönnt.

Dabei kam die Idee auf, eine schon etwas ältere Idee neu anzupacken, zu verfeinern, sodass etwas richtig gutes, brauchbares hinten rauskommt.
Der Name bleibt gleich wie er schon bei der älteren Idee war "XmlRepository". Nur hat sich basierend auf der älteren Idee und deren Eigenheiten "schlank, einfach, praktisch" etwas viel praktischeres und brauchbareres gegeben, als es der frühere Prototyp war.

XmlRepository - das es auf http://www.xmlrepository.ch/ zum Download gibt, ist wie folgt auf der Seite selber kurz umschrieben:

XML-basiertes, threadsicheres Repository für flache .NET-Objekte, welches
        das Dateisystem und In-Memory unterstützt.


Folgend ein bisschen Beispielcode, damit jeder sich ein ungefähres Bild der Anwendung machen kann:

        XmlRepository.DefaultQueryProperty = "Id";
        XmlRepository.DataProvider = new XmlFileProvider("~/App_Data/");

        using(var repository = XmlRepository.GetInstance<Foo>) {
            var foos = repository.LoadAllBy(f => f.Id > 42);
            repository.SaveOnSubmit(new Foo { Id = 27, ... });
            repository.DeleteOnSubmit(f => f.Id == 23);
        }


XmlRepository ist aus unserer Sicht entwickelt und sehr geeignet für:
  • Schnell Prototypen mit simplen Datenstrukturen entwerfen
  • Einfache und schnelle Einbindung einer Datenquelle für Datenstrukturen von einfacher bis mittlerer Komplexität
  • Sehr für Projekte (Web / Client) geeignet, die nicht einen sehr grossen Datenbestand, sowie wenig Schreibende Zugriffe zu verzeichnen hat
  • Sehr effiziente, typsichere und bequeme Alternative für manuelle XML-Anbindung
Auch wenn bei dir, werter Leser, kein Anwendungfall zutreffen mag, kann man von jedem Code lernen. Ob es jetzt sei, wie man etwas nicht macht - oder wie man es auch noch - oder besser - machen könnte.
Eingetragen von Peter Bucher | 2 Kommentare
Mehr Beiträge Nächste Seite »