Generische Methode um gleichnamige Properties einer Klasse zu einem Objekt einer anderen Klasse zu kopieren – C#

Bei meiner Arbeit kommt es häufiger vor, dass ich umfangreiche Klassen (welche die Daten einer Datenbank repräsentieren) verwende die mal schnell über 50 oder 100 Public Properties (Datenbankfelder) enthalten.

imageNun kommt immer wieder vor, dass ich zum Beispiel zum Archivieren solcher Daten, damit meine ich die Daten aus einer Tabelle in eine andere zu verschieben, nicht auf SQL Skripte auf dem Server zugreifen kann oder möchte, da dieses verschieben noch mit zusätzlicher Businesslogik hinterlegt werden muss.

Was bleibt ist dann so etwas in dieser Art:

var auftrag = new Auftrag
    { Position = 1, Artikel = "Mars", Beschreibung = "Schoko Riegel", Preis = 1.50 };

var auftragsArchiv = new AuftragArchiv();
auftragsArchiv.Artikel = auftrag.Artikel;
auftragsArchiv.Beschreibung = auftrag.Beschreibung;
auftragsArchiv.Preis = auftrag.Preis;

if (auftragsArchiv.Save())
{
    auftrag.Delete();
}

Diese Vorgehensweise kann bei umfangreichen Klassen sehr arbeitsintensiv sein.

Nun gibt es verschiedene Ansätze um sich diesem Problem anzunehmen. Nachfolgend möchte ich einige Lösungsansätze unter Verwendung von Reflection aufzeigen.

Ich nehme an, jeder kennt die Methode ToString().

Die Idee ist nun eine generische To…. Methode zu erstellen, welche die Aufgaben wie im obigen Beispiel dargestellt, universell erledigt.

Das Ziel soll sein, dass die Public Property Werte eines Objektes, durch Aufruf einer Methode, alle Werte die den gleichen Property Namen  haben in ein anderes Objekt einer anderen Klasse kopiert werden.

Hier nun die Variante 1 (Methode einer Klasse):

public T ToTobject<T>(T target)
{
    const BindingFlags Flags = BindingFlags.Instance | BindingFlags.Public;
    var sourceProperties = this.GetType().GetProperties(Flags);

    foreach (PropertyInfo pi in sourceProperties)
        {
            if (pi.CanWrite)
            {
				var propInfoObj = target.GetType().GetProperty(pi.Name);
				if (propInfoObj != null)
				{
					var propValue = pi.GetValue(this, null);
					propInfoObj.SetValue(target, propValue, null);
				}                             
            }
        }

    return target;
}

Der Aufruf um diese Variante zu verwenden sieht dann so aus:

var auftrag = new Auftrag
	{ Position = 1, Artikel = "Mars", Beschreibung = "Schoko Riegel", Preis = 1.50 };

var auftragsArchiv = new AuftragArchiv();

auftragsArchiv = auftrag.ToTobject(auftragsArchiv);

if (auftragsArchiv.Save())
{
	auftrag.Delete();
}

Sieht doch schon ganz gut aus.

Hier noch eine Variante, die noch etwas mehr generisch arbeitet und nur noch mitgeteilt bekommt, welchen Type ich als Rückgabe der Methode erwarte, die Instanz des Objekts der neuen Klasse wird in der Methode selbst erzeugt.

public T ToTobject<T>()
{
	var constructorInfo = typeof(T).GetConstructor(new Type[] { });
	if (constructorInfo != null)
	{
		var target = (T)constructorInfo.Invoke(new object[] { });

		const BindingFlags Flags = BindingFlags.Instance | BindingFlags.Public;
		var sourceProperties = this.GetType().GetProperties(Flags);

		foreach (PropertyInfo pi in sourceProperties)
		{
			if (pi.CanWrite)
			{
				if (!pi.IsDefined(typeof(XmlIgnoreAttribute), false))
				{
					var propInfoObj = target.GetType().GetProperty(pi.Name);
					if (propInfoObj != null)
					{
						var propValue = pi.GetValue(this, null);
						propInfoObj.SetValue(target, propValue, null);
					}
				}
			}
		}

		return target;
	}

	return default(T);
}

Diese Variante wird dann so verwendet:

var auftrag = new Auftrag
	{ Position = 1, Artikel = "Mars", Beschreibung = "Schoko Riegel", Preis = 1.50 };

var auftragsArchiv = auftrag.ToTobject<AuftragArchiv>();

if (auftragsArchiv.Save())
{
	auftrag.Delete();
}

Diese Variante gefällt mir schon etwas besser

Aber das ist noch nicht das Ende der Methoden Evolution!

Es geht noch generischer (und statisch für alle Klassen verwendbar) und diese Variante folgt nun.

public static T ToTobject<T>(object source)
{
	var constructorInfo = typeof(T).GetConstructor(new Type[] { });
	if (constructorInfo != null)
	{
		var target = (T)constructorInfo.Invoke(new object[] { });

		const BindingFlags Flags = BindingFlags.Instance | BindingFlags.Public;
		var sourceProperties = source.GetType().GetProperties(Flags);

		foreach (PropertyInfo pi in sourceProperties)
		{
			if (pi.CanWrite)
			{
				var propInfoObj = target.GetType().GetProperty(pi.Name);
				if (propInfoObj != null)
				{
					var propValue = pi.GetValue(source, null);
					propInfoObj.SetValue(target, propValue, null);
				}
			}
		}

		return target;
	}

	return default(T);
}

Diese nun statische Variante kann auf jedes beliebige Objekt jeder beliebigen Klasse angewendet und für die Rückgabe jeder beliebigen Klasse verwendet werden. Natürlich nur solange diese Klassen auch gleiche Properties enthalten.

Und so wird diese statische Methode verwendet:

var auftrag = new Auftrag
	{ Position = 1, Artikel = "Mars", Beschreibung = "Schoko Riegel", Preis = 1.50 };

var auftragsArchiv = Auftrag.ToTobject<AuftragArchiv>(auftrag);

if (auftragsArchiv.Save())
{
	auftrag.Delete();
}

Mir hat es Spaß gemacht diese Methodik zu entwickeln, evtl. hilft es auch mal jemand anderem beim Lösen “seines” Problem.

Anregungen und Kritik wie immer gerne als Kommentar zum Beitrag.

ASCII Schnittstellen mit Hilfe von Custom Attributes komfortabel erstellen – C#

Viele kennen dass Problem, dass Daten zwischen verschiedenen Welten auch Heute noch immer durch Übergabe von Schnittstellendateien, seien es EDI oder auch ASCII Dateien, die einen festen Satzaufbau haben, übergeben werden.

Die Definitionen sehen oft wie folgt aus:

Wobei die nähere Definition etwas komplexer sein kann:

Art: A alphanumerisches Feld N numerisches Feld Länge L Gesamtlänge des Datenfeldes Nachkomma K davon Nachkommastellen Position von von Stelle ... im Datensatz bis bis Stelle ... im Datensatz M/O M Muss-Feld O Kann-Feld (optional) M/O abhängig von anderen Angaben handelt es sich wahlweise um ein Muss- oder ein Kann-Feld

Der Output, also die Übertragungsdatei enthält dann Daten die ähnlich der nachfolgenden Abbildung aussehen können.

image

Eine durchaus übliche Vorgehensweise solche Daten erstellen zu können ist es, sich Klassen zu erstellen, die dem eigentlichen benötigten Satzaufbau entsprechen, diese in einer Füll Routine mit Daten füllt und anschließend die Daten der Klasseneigenschaften mit string.Format Stück für Stück ausgibt.

Wäre es nicht wünschenswert, bereits bei der Definition der Klasse festlegen zu können, welche Ausgabeeigenschaften (Ausgabeformat wie führende Nullen, Links oder Rechtsbündig, Anzahl Nachkommastellen usw.) die jeweilige Eigenschaft besitzt und an welcher Position die Eigenschaft ausgegeben werden soll, anzugeben, damit man anschließend die Daten einfach mit einer einzelnen Methode im richtigen Format ausgeben kann.

Und genau da setze ich mit meiner Lösung an:

Man kann mit sogenannten Custom Attributes beliebig zusätzliche Informationen an jedes beliebige Klassenelement anheften. Hierzu muss man eine Klasse erstellen die von System.Attributes abgeleitet wird.

Siehe Nachfolgendes Beispiel, welches ziemlich selbsterklärend sein sollte.

using System;
    using System.Reflection;

    public enum ExportFieldType
    {
        /// <summary>
        /// Alphanumeric Field
        /// </summary>
        Alpha,

        /// <summary>
        /// Numeric Field
        /// </summary>
        Numeric
    }

    [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
    public class ExportFieldAttribute : Attribute
    {
        private readonly int index;

        private readonly int length;

        private readonly ExportFieldType fieldType;

        private readonly int precision;

        private readonly bool optionalField;

        private readonly int fromPos;

        private readonly int toPos;

        /// <summary>
        /// Initializes a new instance of the <see cref="ExportFieldAttribute"/> class.
        /// </summary>
        /// <param name="index">The index.</param>
        /// <param name="fieldType">Type of the field.</param>
        /// <param name="length">The length.</param>
        /// <param name="precision">The precision.</param>
        /// <param name="optionalField">if set to <c>true</c> [optional field].</param>
        /// <param name="fromPos">From pos.</param>
        /// <param name="toPos">To pos.</param>
        public ExportFieldAttribute(int index, ExportFieldType fieldType, int length, int precision, bool optionalField = false, int fromPos = -1, int toPos = -1)
        {
            this.index = index;
            this.fieldType = fieldType;
            this.length = length;
            this.precision = precision;
            this.optionalField = optionalField;
            this.fromPos = fromPos;
            this.toPos = toPos;
        }

        public int Index
        {
            get
            {
                return this.index;
            }
        }

        public ExportFieldType FieldType
        {
            get
            {
                return this.fieldType;
            }
        }

        public int Length
        {
            get
            {
                return this.length;
            }
        }

        public int Precision
        {
            get
            {
                return this.precision;
            }
        }

        public bool OptionalField
        {
            get
            {
                return this.optionalField;
            }
        }

        public int FromPos
        {
            get
            {
                return this.fromPos;
            }
        }

        public int ToPos
        {
            get
            {
                return this.toPos;
            }
        }
    }

Nun kann ich in der Klassendefinition in der ich die Datensatzstruktur der Exportdatei abbilde, dieses Attribut zusätzlich zu den Eigenschaften der Klasse verwenden um die für den korrekten Export benötigen Informationen anzuheften.

Die Klasse könnte so aussehen:

    public class Ksta
    {
        [ExportField(0, ExportFieldType.Alpha, 5, 0)]
        public string Satza
        {
            get
            {
                return "KSTA_";
            }
        }

        [ExportField(1, ExportFieldType.Numeric, 2, 0)]
        public int Gsber
        {
            get
            {
                return 1;
            }
        }

        [ExportField(2, ExportFieldType.Numeric, 8, 0)]
        public int Kvkda { get; set; }

        [ExportField(3, ExportFieldType.Numeric, 8, 0)]
        public int Dtkda { get; set; }

        [ExportField(4, ExportFieldType.Numeric, 5, 0)]
        public int Kvkvn { get; set; }

        [ExportField(5, ExportFieldType.Numeric, 5, 0)]
        public int Ssbpa { get; set; }

        [ExportField(6, ExportFieldType.Numeric, 8, 3)]
        public int Sskda { get; set; }
    }

Wie aber können wir diese zusätzlichen Attribute verwenden?

Ich möchte dies an einem einfachen Beispiel demonstrieren. Hierzu erweitere ich die Klasse ExportFieldAttribute um folgende Methode:

public static string ExportFieldToString(object obj, bool sorted = true)
{
	string buffer = string.Empty;
	PropertyInfo[] pi = obj.GetType().GetProperties();
	if (sorted)
	{
		var propertyInfoSorted = new PropertyInfo[pi.Length];
		foreach (var propertyInfo in pi)
		{
			var attribs = (ExportFieldAttribute[])propertyInfo.GetCustomAttributes(typeof(ExportFieldAttribute), true);
			if (attribs.Length > 0)
			{
				propertyInfoSorted[attribs[0].Index] = propertyInfo;
			}
		}

		pi = propertyInfoSorted;
	}

	foreach (var propertyInfo in pi)
	{
		if (propertyInfo == null)
		{
			continue;
		}

		var attribs = (ExportFieldAttribute[])propertyInfo.GetCustomAttributes(typeof(ExportFieldAttribute), true);

		if (attribs.Length > 0)
		{
			ExportFieldAttribute attrib = attribs[0];
			var o = propertyInfo.GetValue(obj, null);
			if (o == null)
			{
				o = string.Empty;
			}

			if (attrib.FieldType == ExportFieldType.Alpha)
			{
				string t = string.Format(o.ToString().PadRight(attrib.Length));
				buffer += t;
			}

			if (attrib.FieldType == ExportFieldType.Numeric)
			{
				if (attrib.Precision > 0)
				{
					string concat;
					var buf = o.ToString().Split(',');
					if (buf.Length > 1)
					{
						buf[1] = buf[1].PadRight(attrib.Precision, '0').Substring(0, attrib.Precision);
						concat = buf[0] + buf[1];
					}
					else
					{
						concat = buf[0] + string.Empty.PadRight(attrib.Precision, '0');
					}
					string t = string.Format(concat.PadLeft(attrib.Length, '0'));
					buffer += t;
				}
				else
				{
					string t = string.Format(o.ToString().PadLeft(attrib.Length, '0'));
					buffer += t;
				}
			}
		}
	}
	return buffer;
}

Ich möchte an dieser Stelle nun auch keine aufwändige Erklärung der Methode vornehmen, ich denke dass derjenige der sich mit diesem Problem beschäftigt erkennen wird was darin geschieht.

Und um diese Methode zu verwenden, also um den Satzaufbau der Daten so zu erhalten wie ich ihn mit den Attributen definiert habe, überschreibe ich einfach die ToString() Methode der Klasse in welcher ich die Datenstruktur abgebildet habe.

Das sieht dann so aus (In der Klasse Ksta):

        public override string ToString()
        {
            return ExportFieldAttribute.ExportFieldToString(this);
        }

Wenn ich nun eine Instanz der Klasse Ksta erstelle, diese dann mit Daten fülle und anschließen die ToString Methode aufrufe erhalten ich die Daten genau in der definierten Struktur.

Wenn jemand noch Fragen zu dem Thema hat, oder doch noch weiterführende Erläuterungen benötigt, dann einfach per Kommentar die Fragen oder Anregungen stellen.

Windows 8 – Irrweg oder einfach ein Irrer Weg

Es ist nun eine Woche her (13.09.2011), das Microsoft in Anaheim / Florida auf der “BUILD Windows” das Geheimnis um Windows 8 gelüftet hat.

Nun liegen die Fakten um Windows 8 auf dem Tisch!

  • Doch stehen die Fakten mit der Präsentation von Windows 8 wirklich fest?
  • Was wurde uns eigentlich als Windows 8 verkauft?
  • Worüber freuen wir uns?
  • Worüber ist die eine oder andere Gruppe betrübt?

Um diese Fragen und die meine Wahrheit um Windows 8 zu klären,  müssen wir aber auch die jüngere Vergangenheit vor der Öffentlichen Präsentation von Windows mit einbeziehen.

Denn die eigentliche Geschichte um Windows 8 beginnt bereits einige Wochen vor der BUILD in Anaheim.

Was ist in den letzten Wochen wirklich geschehen:

In den Tagen und Wochen vor der BUILD wurde viel Spekuliert.
Teilweise wurden echte Schreckensszenarien vermittelt.
Leider wurde auch von, sonst sachlich und nüchtern berichtenden Kollegen, mit Meldungen wie den folgenden Schlagzeilen gemacht:

  • HMTL 5 und JavaScript werden zur Standard Sprache zur Entwicklung von Desktop Anwendungen
  • Silverlight wird als Technologie nicht mehr unterstützt
  • Die Zukunft um WPF ist ungewiss
  • .NET wird es nicht mehr geben oder aussterben und damit wird auch C# und VB verschwinden
  • HTML 5 und vor allem JS sind die “must be” Sprachen für jeden Entwickler, sonst ist für Ihn/Sie der Zug abgefahren.
  • …. und ganz vieles Mehr.

Unabhängig davon, ob und wie viel davon tatsächlich irgendeiner Wahrheit nahe kommt, haben all diese Überlegungen und Gerüchte darauf basiert, dass davon ausgegangen wurde,  dass mit Windows 8 direkt von einem Nachfolger des Windows 7 wie wir es Heute kennen, einem reinen Desktopbetriebssystem,  gesprochen wird.

Doch was haben wir auf der BUILD wirklich vorgestellt bekommen?

  • Eine zu groß geratene Ausgabe von Windows Phone WP7
  • Ein neues Tablet Betriebssystem
  • Der Nachfolger des Windows 7 Desktop Betriebssystems

Ein wenig von allem!

Präsentiert hat uns Microsoft natürlich “das Neue”, das was man direkt sieht, das was vollkommen anders ist wie bisher, das was dem aktuellen Trend entspricht, das was Hype verspricht, das was ….

Das was präsentiert wurde, war die “Metro Style Oberfläche”

win8 - metro

Und dieses neue, ist doch genau das, was uns entweder empört oder begeistert hat.

Je nachdem welcher Zielgruppe man angehört, findet man diese Neuerung als “vollkommen abgefahren”, “Super Innovativ”“vollkommen daneben” oder als “Weltuntergang”.

Und ich glaube es gibt mehr Zielgruppen als wir uns das momentan überhaupt vorstellen können.

Allerdings sind die Zielgruppen, die sich bisher mit Windows 8 beschäftigt haben und sich öffentlich darüber geäußert haben, doch eher die aus dem Umfeld derer, welche sich mit der Entwicklung von Software beschäftigen, und für all diese, oder besser gesagt für die meisten von diesen, bedeutet Neuerung und Veränderung natürlich erst einmal die Angst vor Verlust.

Angst vor Verlust, Angst davor dass Wissen das man sich Jahrelang angeeignet hat, nicht weiter verwenden zu können.

Und wenn ich mir das anschaue, was Microsoft uns auf der BUILD als WIN 8 präsentiert hat, dann habe ich als Entwickler von Business Anwendungen (Egal ob als Web Anwendung, Desktopanwendung oder im Backend als Server Anwendung) im ersten Moment auch diese Angst (ganz kurz) verspürt.

Doch als analytischer Mensch lässt man sich natürlich nicht von einem Schauer der einem über den Rücken läuft lähmen und man beginnt die Sache, in diesem Fall Windows 8, mit dem notwendigen Abstand und der notwendigen Sorgfalt von den verschiedensten Seiten zu betrachten.

Ich habe die letzte Woche genutzt um mir Windows 8 genauer anzuschauen und mir Gedanken über die Auswirkungen von Windows 8 auf meinen Job als Entwickler zu machen.

Nachfolgend hierzu meine Gedanken und Thesen.

Metro Style Apps

Metro Style Apps sind nur auf Geräten mit Touch Bedienung sinnvoll einzusetzen.

Microsoft hat als Vision, dass es in Zukunft nur noch Geräte mit Touch Interface geben wird, und daher auf jedem Gerät Metro Style Apps sinnvoll eingesetzt werden können. Dem möchte ich auch nicht wiedersprechen, doch denke ich nicht, dass wir diese Zukunft noch dieses Jahrzehnt erleben werden.

Metro Style Apps werden für mich, meinen Job und meine Kunden mit oder ohne Windows 8 (damit meine ich die nächsten 2 – 3 Jahre) noch nicht wirklich eine entscheidende Rolle spielen.

Metro Style Apps werden weder Heute noch Morgen (mal schauen was übermorgen geschieht und ob dann noch jemand von Metro Style Apps spricht) als Ersatz für Rich Client Desktop Anwendungen im Büro und Produktionsstätten geeignet sein.

Wenn solche Art von Apps überhaupt für Rich Client Anwendungen eingesetzt werden sollten, wird das sicherlich noch bis Ende des Jahrzehnts und darüber hinaus dauern.

Um es nicht später zu vergessen:

Einen Wunsch an Microsoft bezüglich Windows 8 und der Metro Style Oberfläche hätte ich aber schon:

Hallo Microsoft, lasst bei der Installation von Windows 8 per Option entscheiden, welchen Desktop man als Standard verwenden möchte, den Metro Style oder den Standard Desktop  (WIN 7 Like)

Und eines noch Microsoft, solltet Ihr auf die Idee kommen, die in der Windows 8 Preview vorhandenen Möglichkeit, durch Änderung eines Registry Eintrags ein “Windows 7 Like” Startmenü zu bekommen, aus dem Final Release von WIN 8 gänzlich zu entfernen, sage ich euch mit WIN 8 ein zweites VISTA voraus (auf  jeden Fall auf Desktop PCs)

win8 - api

WinRT

Mit der WinRT stellt Microsoft den zentralen Baustein für die neue Metro Style Oberfläche zur Verfügung.

WinRT wird nicht als zusätzlicher Framework sondern als integraler Bestandteil des Betriebssystems betrachtet.

Ob WinRT wirklich eine Lösung oder mehr ein Problem ist, wird sich im Laufe der Zeit zeigen.
Ich finde es, Stand Heute sehr gewagt mit WinRT auf eine Technik wie COM (auch wenn es ein objektorientierter modernerer Ansatz ist) zurückzugreifen, die man vor fast 10 Jahren, aus guten Gründen, durch die .NET Technologie abgelöst hatte.
Einzig die Tatsache dass es in WinRT außer den WinRT eigenen DLLs keine gemeinsamen Bibliotheken gibt lässt mich hoffen, dass es kein zweite DLL Hölle geben wird.

Wer in Manage Code C# oder VB Metro Style Apps schreiben will muss sich im klaren sein, dass man dabei starken Beschränkungen unterliegt, da die WinRT nur eine Teilmenge der .NET Klassen zur Verfügung stellt.

Dinge wie direkte Dateizugriffe, Zugriffe aufs Dateisystem oder auch zugriffe auf eine Datenbank wie SQL oder andere sind nicht direkt möglich.

Um Beispielsweise auf eine Datenbank zugreifen zu können muss man sich zuerst einen Web Service erstellen, den man dann über die WinRT aufrufen kann.

Damit die Metro Style Apps immer den Eindruck hervorrufen dass Sie auf Benutzereingaben sofort reagieren, wurde in der WinRT darauf geachtet, dass alle Aufrufe die im allgemeinen länger als 50 ms dauern Asynchron aufgerufen werden.

.NET (C# 5 und VB)

.NET ist also noch nicht tot.

Neben Metro Style und dem damit zusammenhängenden WinRT wurde auch am .NET Framework gearbeitet.

Das .NET Framework 4.5 wird zusammen mit Windows 8 ausgeliefert (gibt es aber auch für Windows 7).

Zusammen mit dem Framework gehen auch die Managed Code Sprachen C# und VB in die nächste Versionsrunde.

  • C# 5.0
  • Visual Basic 11.0

Die umfangreichste Erweiterung der Sprachen besteht wohl in der Implementierung der await und async Schlüsselwörter und der damit einhergehenden Vereinfachung der Asynchronen Programmierung.

Die Zukunft von .NET dürfte wohl für die nächsten Jahre zumindest für “echte” Desktop Anwendungen” sowie natürlich für Web und Backend Anwendungen, gesichert sein.

HMTL 5 und JavaScript

Weder HMTL 5 noch JavaScript, und auch nicht die Kombination der beiden Sprachen, sind eine Erfindung von Windows 8.

Jedoch wird diese Kombination sicherlich nicht nur für die Web Entwicklung immer interessanter und wer sich bis Heute nicht damit beschäftigt hat, ist sicherlich gut beraten sich mit diesem Thema in näherer Zukunft auch ein wenig auseinanderzusetzen.

Ganz sicher dann, wenn man nicht nur Backend Programmierung betreibt.

Silverlight

Meiner ganz persönlichen Meinung nach, sieht die Zukunft von Silverlight nicht so rosig aus. Ich denke dass Silverlight mittelfristig zu den Klassischen Verlierern zählen wird und weder weiter entwickelt noch auf ewig weiter unterstützt werden wird.

Rich Web Applikationen können mit anderen Technologien wie HTML 5 zusammen mit JS auf der Client Seite erstellt und zusätzlich noch durch MVC oder ähnliche Technologien (evtl. auch mal durch node.JS) Serverseitig unterstützt werden.

Wenn man sieht, dass der IE10 in der Metro Style Variante keine Add Ins und somit kein Silverlight und kein Flash mehr unterstützt, muss man nur 1 und 1 addieren um sich über die Zukunft on SL seine Gedanken machen zu können.

Mein Tipp: Wenn du merkst, dass du ein totes Pferd reitest, steig ab!

Resümee und Weisheiten

Die Suppe wird nie so heiß gegessen wie Sie gekocht wird.
.NET lebt auch nach Windows 8 weiter, wir müssen nicht alle sofort nur noch HTML 5 und JS Programme schreiben

Der Markt und die Akzeptanz regelt im allgemeinen ganz viel alleine (Siehe VISTA), also wenn Windows 8 letztendlich wirklich nur per Touch ordentlich zu bedienen sein wird, dann wird es vermutlich ein Tablet OS aber kein Nachfolger für Windows 7

Warten wir mal ab wie Windows 8 in der Final Release dann wirklich auf den Markt kommt.

Eines habe ich übrigens vergessen, und das ist der bisher positivste Aspekt des neuen Windows:

Windows 8 startet um ein vielfaches schneller als jede andere Windows Version die es bisher gab.

Abschließen möchte ich, auch wenn dies kein Bericht über ein Fußballspiel war, mit den Worten eines großen Deutschen Fußballers:

Nach dem Spiel ist vor dem Spiel!

Freuen wir uns schon mal auf die Gerüchte und Aufregung um Windows 9.

DotNetNuke 6.0 Final Release – Ein letztes großes VB.NET Projekt wird zu Grabe getragen

Mit dem Finalen Release 6.0 des Open Source CMS Frameworks DotNetNuke wird unter anderem auch eines der letzten großen VB.NET Open Source Projekte sein Ende finden.

Da eine Migration eines DotNetNuke 5 Portals nach 6.0 keine größeren Umstände bereiten sollte, ist zu vermuten und auch zu hoffen, dass mit der Version 5.6.3 die letzte VB.NET Version von DotNetNuke veröffentlicht wurde und die zukünftige Entwicklung komplett auf Basis der C# Version fortgeführt wird.

Die Highlights sind:

  • Umstellung des Framework von VB.NET auf C#
  • Die UI/UX wurden komplett überarbeitet (wem es gefällt)
  • Windows Azure kompatibel
  • SQL Azure kompatibel

DotNetNuke 6 kann direkt über das Open Source Community Portal Codeplex heruntergeladen werden.

Hier geht es direkt zum Download

DotNetNuke 6 RC (Release Candidate) steht zum Download bereit

Nach 8 Monaten Entwicklungszeit steht nun seit Gestern Abend der Release Candidat der Version 6, der ersten C# Version von DotNetNuke zum Download zur Verfügung.

Der Release Candidate hat die Build Nummer 2962 und kann auf www.codeplex.com heruntergeladen werden.

Hier geht es direkt zum Download auf Codeplex

DotNetNuke 6.0 Beta – Ein erster schneller Eindruck

Nachdem vor 2 Tagen die erste Beta Version von DotNetNuke 6.0 veröffentlicht wurde möchte ich Heute kurz einen ersten Eindruck, zu den aktuellen Neuerungen und dem Stand der Umsetzung, abgeben.

Hier die Key Feature der Version 6.0

  • Bereits bekannt aber natürlich ein Riesenschritt (Umstellung des Core auf C#)
  • Verwendung von Razor möglich
  • Popup Fenster (JavaScript und noch mehr JavaScript)
  • Seiten Administration komplett geändert
  • Telerik Editor anstelle dec FCK Editors (mal wieder)
  • … und noch einiges mehr
  • Und eigentlich sollte auch mit 6.0 die Content Lokalisierung komplett implementiert sein (Hoffentlich ist das nicht dem Razor Wahn zum Opfer gefallen)

Nach der Installation fällt sofort auf,  dass nichts mehr ohne Javascript geht.

Hier ein Javascript, da ein Popup (wer es mag) und dort wieder ein Script !

Ich finde schon das JavaScript und Popup Fenster an manchen Stellen dezent eingesetzt die Useability erhöhen können, aber wenn es nur noch popt und tabed kann es auch leicht mal unübersichtlich werden.

So ganz sicher scheint man sich aber auch noch nicht zu sein, denn wenn man die neue Seitenadministration sieht, da hat man auf das ganze Popup verzichtet, oder hat man das einfach bisher vergessen 😉

Und natürlich musste auch bei DotNetNuke unbedingt Razor mit eingebaut werden, ich habe hierzu bereits meine Meinung im Beitrag über die BlogEngine 2.5 RC abgegeben.

Echt kritisch ist aber, dass die Administration eines Portals dieser Beta Version mit dem IE9 quasi nicht möglich ist. Mit Chrome scheint aber soweit alles zu funktionieren.

Ich werde mir in den nächsten Tagen die Beta Version auf jeden Fall noch genauer ansehen und sicherlich auch noch den einen oder wenn nötig auch anderen  Beitrag darüber veröffentlichen.

Stand Heute würde ich aber vermuten, dass dies nicht die letzte Beta Version war, bevor es dann irgendwann zum einem RC kommt.

DotNetNuke – Nach C kommt B oder anders gesagt, nach der CTP3 ist nun die Beta 1 Verfügbar

Heute wurde die erste öffentliche Beta Version von DotNetNuke 6.0 veröffentlicht.

Somit ist nach über 3 Monaten (da wurde die letzte CTP Version veröffentlicht) in der sich nichts neues ergeben hat, nun endlich eine aktuellere Version vorhanden.

Ersten Meldungen zu folge gibt es mit dieser Beta Version Probleme mit dem IE9, aber das ist leider nicht wirklich etwas neues.

Mit Chrome soll es diese Probleme übrigens nicht geben (auch nicht neues 🙂 )

Hier geht es direkt zum Download der aktuellen Beta Version DotNetNuke 6.0

Schauen wir mal was uns mit dieser Beta erwartet.

DotNetNuke – FolderController – Obsolete Klasse

Im vorläufig letzten Teil meiner kleinen Serie „Clean Code meiner DotNetNuke Module“ geht es Heute um eine ganze Klasse, welche unter DotNetNuke 6.0 nicht mehr weiter verwendet werden soll.

Die Klasse wird mit Obsolete gekennzeichnet und soll durch die neue Klasse FolderManager ersetzt werden.

Allerdings trifft dies nicht für alle Methoden aus der alten Klasse FolderController zu.

Ich hatte in einem meiner Module den nachfolgenden Code eingesetzt um aus einem virtuellen Verzeichnis den absoluten Pfad auf dem Server zu ermitteln.

FolderController folderController = new FolderController();
string mappedTargetModuleFolder = folderController.GetMappedDirectory(portalFolder);

Nun sucht man in der neuen Klasse FolderManager aber vergebens nach einer Ersetzung für diese Methode.

Doch gibt es natürlich auch hiefür eine Lösung.

Im Namespace DotNetNuke.Common.Utilities finden wir die Klasse PathUtils und diese Klasse enthält eine Methode MapPath, die genau die Funktionaltität der zu ersetzenden Methode aus der Klasse FolderController erfüllt.

Und so sieht dann der Code aus:

string mappedTargetModuleFolder = PathUtils.Instance.MapPath(portalFolder);

DotNetNuke – GetModuleDefinitionByName – Obsolete

Heute geht es in meiner Serie „Clean Code meiner DotNetNuke Module“ um die Methode GetModuleDefinitionByName() aus dem Namespace
DotNetNuke.Entities.Modules.Definitions.ModuleDefinitionController.

Der Einsatz dieser Methode war immer schone etwas umständlich da man nicht direkt den Friendly Name verwenden konnte sondern dieser erst über den Umweg des DesktopController ermitteln musste.

Um wie im folgenden Beispiel die ModuleDefId einer Moduls ermitteln zu können, musste man 2 verschiedene Controller Klassen ansprechen.

  • ModuleDefinitionController
  • DesktopModuleController

Diese Methode wurde bereits mit der Version 5.0 ersetzt.

Bis zur Version 5 wurde die Methode wie folgt verwendet:


ModuleDefinitionController moduleDefinitionController = new ModuleDefinitionController();
int newModulDefId = moduleDefinitionController.GetModuleDefinitionByName(
desktopModuleController.GetDesktopModuleByName("DNNPortal-Download").DesktopModuleID, 
"DNNPortal-Download").ModuleDefID;

Hier nun der Aufruf mit der neuen Methode:


int newModulDefId = ModuleDefinitionController.GetModuleDefinitionByFriendlyName("DNNPortal-Download").ModuleDefID;

DotNetNuke – PortalSecurity.HasEditPermissions – Obsolete

In der Serie Clean Code meiner DotNetNuke Module geht es Heute um die Methode PortalSecurity.HasEditPermissions().

Ebenfalls seit der DotNetNuke Version 5.0 ist die Methode HasEditPermissions() aus dem Namespace DotNetNuke.Security.PortalSecurity nicht mehr zu verwenden.

Die beschriebene Methode wird dazu verwendet, zu ermitteln ob der angemeldete Benutzer die Rechte zur Bearbeitung für ein bestimmtes Modul besitzt.

Ein Aufruf, der bis zur Version 5.0 wie folgt ausgesehen hat:


if (PortalSecurity.HasEditPermissions(ModuleId, TabId))

sollte nun durch den nachfolgenden Aufruf ersetzt werden.


if(ModulePermissionController.HasModuleAccess(
SecurityAccessLevel.Edit,
"EDIT",
this.ModuleConfiguration))

Mehr folgt in Kürze