Kategorien

Weblog Liste

Archiv

Administration

Sign In
 Tuesday, December 12, 2006
Tuesday, December 12, 2006 6:25:27 PM (Mitteleuropäische Zeit, UTC+01:00) #
Comments [0]

Wie versprochen nun die Fortsetzung.

Um "beliebige" Objekte lesen und schreiben zu können, bediene ich mich der Serialisierungmöglichkeiten von .NET. Es werden zwei neue Methoden eingeführt GetObject<T> und SetObject<T>. Die Implementierung dieser Methoden sieht dann wie folgt aus.

// <summary>
/// Gets the object.
/// </summary>
/// <param name="node">The node.</param>
/// <returns></returns>
private static T GetObject<T>(XmlNode node)
{
T result = default(T);

    //restore object from node
XmlSerializer ser = new XmlSerializer(typeof(T));
result = (T)ser.Deserialize(new StringReader(node.OuterXml));

return result;
}

/// <summary>
/// Sets the object.
/// </summary>
/// <param name="node">The node.</param>
/// <param name="value">The value.</param>
private static void SetObject<T>(XmlNode node, T value)
{
if(value == null)
{
return;
}

using(MemoryStream stream = new MemoryStream())
{
//serialize object
XmlSerializer ser = new XmlSerializer(typeof(T));
ser.Serialize(stream, value);

//reset read position
stream.Position = 0;

XmlElement newNode = null;

using(XmlReader reader = XmlReader.Create(stream))
{
//move to the content node.
reader.MoveToContent();
//create new element in node context
newNode = node.OwnerDocument.CreateElement(reader.Name);
//set content
newNode.InnerXml = reader.ReadInnerXml();
}

//append the new node
node.AppendChild(newNode);
}
}
Die beiden Methoden können natürlich auch public gemacht werden, damit sie explizit aufgerufen werden können. Diese Variante ist im Falle einer reinen Hilfsklasse für unterschiedlichste Projekte in der Tat auch vorzuziehen, da es die Verwendungsmöglichkeiten besser hervorhebt.

Im konkreten Beispiel habe ich sie einfach als zusätzlichen Aufruf in die Methoden SetValue<T> und GetValue<T> eingebaut. Irgendwie muß ich ja mein Versprechen erfüllen, mich von der IConvertible-Schnittstelle zu trennen. Nun noch kurz die geänderten Bereiche obiger Methoden, dann sollte ich meiner Verpflichtung nachgekommen sein. :-)

public static T GetValue<T>(XmlNode node, T @default)
{
    ...
    if(!IsConvertible(typeof(T)))
    {
        //get complex object
        result = GetObject<T>(node);
        result = result != null ? result : @default;
    }
    else
    {
        ...
    }
    ...
}

public static void SetValue<T>(XmlNode node, T value)
{
    ...
    if(!IsConvertible(typeof(T)))
    {
        SetObject<T>(node, value);
        return;
    }
    ...
}

Diese Lösung ist ganz klar ein erster Ansatz. Sie weist in dieser Ausprägung noch einige Lücken auf, welche ich nicht verschweigen möchte.
  • Das Löschen von Objektknoten ist in dieser Variante nicht möglich
  • Das Setzen eines komplexen Objektes führt immer zu einem anfügen. Durch die nicht vorhandene Objektidentität wird bei mehrfachen Aufrufen das Objekt auch mehrfach hinzugefügt.
  • Das unterschiedliche Verhalten von Lesen und Schreiben kann zu Irritationen führen.
  • Die XML-Serialisierung kann unter Umständen nicht erfolgreich sein, was dann einige Anforderungen an die Klassen stellt, um dies dennoch zu ermöglichen.

 Monday, December 11, 2006
Monday, December 11, 2006 9:51:53 PM (Mitteleuropäische Zeit, UTC+01:00) #
Comments [3]

Erst komme ich früh nicht aus dem Bett. Gut das ist jetzt nicht so das Problem aber irgendwie fing der Tag damit schon sehr seltsam an.

Nach Feierabend soll ich das Auto von der Arbeitsstelle meiner Frau holen, damit ich sie zu späterer Stunde von ihrer Weihnachtsfeier, diese findet natürlich nicht dort statt, abholen kann. Es kam wie es kommen musste; ich steige in das Auto, starte es, es springt an, geht aus. Suuuuuper.

Mein Auto ist natürlich freundlich und gibt mir einen Hinweis durch eine fröhlich leuchtende Lampe, was wohl sein könnte. Ich schaue ins Handbuch ( oh mann, Handbuch lesen ist feige) und was muß ich da lesen? Die Wegfahrsperre arbeitet nicht korrekt. Suuuuuuuuuper.

Naja, ich schnell zum Telefon gegriffen und meine Frau informiert, dass ich Sie nicht abholen kann und das sich das ganz günstig trifft, da ich mein Feierabendbier in Ruhe schlürfen darf. Man muß den Dingen eben etwas gutes Abgewinnen.

Zu guter Letzt komme ich mit 1,5h Verspätung und den zur Abwechslung mal pünktlichen öffentlichen Verkehrsmitteln nach Hause und mein werter Herr Sohn grinst mich an und erzählt mir eine fadenscheinige Geschichte, warum er die Geschenke für seine morgige Weihnachtsfeier noch nicht gekauft hat. Dabei habe ich ihm am Morgen extra dafür Geld gegeben. Komisch, 6 Stunden hatte Zeit seit Schulschluß, die Story füllt aber nur knapp eine Stunde aber egal. Ein Blick auf den Stubentisch verhindert eine innerliche Atomexplosion, der Schotter liegt noch da, wenigstens etwas. Gut denk ich mir, dann kaufen wir den Spaß eben jetzt. Ich schnappe mir das Kind, damit er auch noch was davon hat, und kaufe das Zeug, zzgl. zwei Packungen Würstchen, weil jeder was zu essen mitbringen soll. Komisch, davon hat er gestern noch nix erzählt. Nur nicht nachdenken, hat wahrscheinlich alles seine Richtigkeit.

Gerade ist meine Frau nach Hause gekommen. Der geneigte Leser möge bemerken: mit dem Auto. Der Ersatzschlüssel, mein Schlüssel (das sagt gar nix aus :)), ist defekt. Suuuuuuuuuuuuuuuper.

Monday, December 11, 2006 7:59:19 PM (Mitteleuropäische Zeit, UTC+01:00) #
Comments [0]

Es ist wirklich interessant welches Laufzeitverhalten .NET beim Vergleichen von Strings zeigt.

Die statische Methode CompareOrdinal des Typs String war, in einem nicht repräsentativen Test, 13mal schneller als sein Bruder seine Schwester Compare, wenn für Compare keine explizite StringComparison angegeben ist. Mit StringComparison.Ordinal lässt sich dann auch Compare dazu überreden, einen schnellen Vergleich durchzuführen.
Leider bezahlt man die verbesserte Performance durch den Verlust der Kulturabhängigkeit. Diese wird jedoch nicht für alle Strings zwingend benötigt.

Achtung: CompareTo ist zwar etwas besser als Compare, mit einem Faktor von 11 aber nicht wesentlich performanter.
Monday, December 11, 2006 9:26:23 AM (Mitteleuropäische Zeit, UTC+01:00) #
Comments [0]

Nachdem mich am Donnerstag ein Virus dahin gerafft hat und ich das Bett hüten durfte, soll es heute wieder was neues geben.


Häufig hat man es mit XML-Daten zu tun, welche ausgelesen und bearbeitet werden sollen. Die enthaltenen Daten sind oft von einem bestimmten Typ. Die nachfolgende Hilfsklasse stellt Schnittstellen zur Verfügung, um die notwendigen Typumwandlungen zu kapseln. Diese Variante funktioniert nur mit Typen welche IConvertible implementieren. Eine Erweiterung, welche diese Einschränkung nicht besitzt, gibt es morgen. :)

using System.Xml;
using System;

namespace de.wwaitz.Utils.XmlHelper
{
public class NodeHelper
{
/// <summary>
/// Gets a value indicating whether T is convertible.
/// </summary>
/// <value>
///     <c>true</c> if T is convertible; otherwise, <c>false</c>.
/// </value>
public static bool IsConvertible(Type resultType)
{
return typeof(IConvertible).IsAssignableFrom(resultType);
}

/// <summary>
/// Gets the value.
/// </summary>
/// <param name="node">The node.</param>
/// <param name="@default">The @default.</param>
/// <returns></returns>
public static T GetValue<T>(XmlNode node, T @default)
{
T result = @default;

if(node == null) {
//invalid node
return result;
}

if(!IsConvertible(typeof(T))) {
//cast is not possible
return result;
}

//get value
string toGet = node.InnerText;
//convert to T
result = (T)Convert.ChangeType(toGet, typeof(T));

return result;
}

/// <summary>
/// Sets the value.
/// </summary>
/// <param name="node">The node.</param>
/// <param name="value">The value.</param>
public static void SetValue<T>(XmlNode node, T value)
{
if(node == null) {
//invalid node
return;
}

if(!IsConvertible(typeof(T))) {
//cast is not possible
return;
}

string toSet = Convert.ToString(value);
node.InnerText = toSet;
}
}
}

Die Verwendung könnte dann wie folgt aussehen:

internal class Program
{
private static void Main(string[] args)
{
string xml = "<root><my-bool>true</my-bool></root>";
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);

bool myBool = NodeHelper.GetValue<bool>(doc.DocumentElement["my-bool"], false);
NodeHelper.SetValue<bool>(doc.DocumentElement["my-bool"], !myBool);
}
}
 Thursday, December 07, 2006
Thursday, December 07, 2006 7:44:08 AM (Mitteleuropäische Zeit, UTC+01:00) #
Comments [1]

Wer auf die gut gemeinten Sprechblasen in der Taskleiste von Windows XP verzichten möchte, kann diese über eine einfache Einstellung in der Registry ausschalten.


Im Registrierungseditor einfach den Schlüssel


HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced


suchen und einen neuen Eintrag mit dem Namen EnableBalloonTips erzeugen. Der Eintrag muß vom Typ DWORD sein. Um die Sprechblasen abzuschalten vergibt man für diesen Eintrag einfach den Wert 0. Wer hätte es gedacht, der Wert 1 schaltet die Tips wieder ein.

 Wednesday, December 06, 2006
Wednesday, December 06, 2006 6:41:09 PM (Mitteleuropäische Zeit, UTC+01:00) #
Comments [0]

Wer wie ich seine Bestimmung eher in der Entwicklung von Anwendungslogik und entsprechenden Konzepten sieht und dessen Begabung nicht in der Erstellung von ansprechenden Webseitenlayouts liegt, sollte sich einmal die Seite Open Source Web Design ansehen.

Für kleine private Projekte wird man hier bestimmt fündig.

 Tuesday, December 05, 2006
Tuesday, December 05, 2006 7:10:02 PM (Mitteleuropäische Zeit, UTC+01:00) #
Comments [1]

Vor einiger Zeit hatte ich mal ein kleines Helferlein geschrieben, um Listen zu sortieren. Gut, das Problem lässt sich eleganter mit delegates lösen aber Spaß hat es trotzdem gemacht. :)

using System;
using System.Collections.Generic;
using System.Reflection;

namespace System.Collections.Generic
{
/// <summary>
/// Ein generischer Algorithmus zum sortieren von Listen.
/// </summary>
public class GenericSort<T> : IComparer<T>
{
private MethodInfo _method;

/// <summary>
/// Erzeugt eine Instanz des Typs
/// [invariant] Der übergebene Member kann eine Methode oder ein Property sein.
/// Handelt es sich um eine Methode, darf sie keinen Parameter
/// besitzen. der Rückgabetyp der Eigenschaft/Methode muß vom Typ
/// IComparable sein.
/// </summary>
/// <param name="member"></param>
public GenericSort(string member)
{
MemberInfo[] infos = typeof (T).GetMember(member);

foreach (MemberInfo info in infos)
{
if (info.MemberType == MemberTypes.Property)
{
if (Initialize((PropertyInfo) info))
break;
}
else if (info.MemberType == MemberTypes.Method)
{
if (Initialize((MethodInfo) info))
break;
}
}

if(_method == null)
throw new InvalidOperationException("Member does not match the class invariant");
}

/// <summary>
/// Initializes the specified info.
/// </summary>
/// <param name="info">The info.</param>
/// <returns></returns>
private bool Initialize(PropertyInfo info)
{
return Initialize(info.GetGetMethod());
}

/// <summary>
/// Initializes the specified info.
/// </summary>
/// <param name="info">The info.</param>
/// <returns></returns>
private bool Initialize(MethodInfo info)
{
if(info.GetParameters().Length > 0)
return false;

if(!typeof(IComparable).IsAssignableFrom(info.ReturnType))
return false;

_method = info;
return true;
}

/// <summary>
/// Compares two objects and returns a value indicating whether one is less than,
/// equal to, or greater than the other.

/// </summary>
/// <param name="x">The first object to compare.</param>
/// <param name="y">The second object to compare.</param>
/// <returns>
/// Value Condition Less than zerox is less than y.Zerox equals y.Greater
/// than zerox is greater than y.

/// </returns>
public int Compare(T x, T y)
{
return ((IComparable) _method.Invoke(x, null)).CompareTo(_method.Invoke(y, null));
}
}
}
Die Sortierung Liste mit Elementen des fiktiven Typs "SomeType" erfolgt dann einfach über nachfolgenden Aufruf:

public class Program
{
    public static void Main(string[] args)
    {
        List<SomeType> list = new List<SomeType>();

        //Code

        list.Sort(new GenericSort<SomeType>("Value"));
    }
}

class SomeType
{
    private int _value;

    public int Value
    {
        get { return _value; }
        set { _value = value; }
    }
}

 Monday, December 04, 2006
Monday, December 04, 2006 12:20:23 PM (Mitteleuropäische Zeit, UTC+01:00) #
Comments [1]


Oh man, manchmal kann es ganz schön nervig werden. Da schreibt man ein schönes Konzeptpapier, versendet es mit den Status "Request for Comment" und nix passiert.



Monate Wochen später kommt die Aufforderung ein neues Konzept zu schreiben, welches auch der Vertrieb versteht. Auf die wiederholte Frage was soll der Inhalt sein und was wurde nicht verstanden, wird genervt reagiert und mir vorgeworfen, ich wolle es gar nicht tun. Dabei habe ich zur Abwechslung einfach mal nicht verstanden, was jetzt von mir gefordert wurde.


Ich sollte nicht immer so Böse schauen.


 Friday, December 01, 2006
Friday, December 01, 2006 8:46:00 PM (Mitteleuropäische Zeit, UTC+01:00) #
Comments [0]


Die ersten Gehversuche mit meinem neuen Drucker habe ich nun beendet. Ich muß sagen, ich bin ganz zufrieden. Das einzige Manko: er beherrscht keinen Duplexdruck. Da habe ich leider nicht darauf geachtet. Ich werde es hoffentlich verschmerzen. Die Netzwerkfähigkeit war mir wichtiger.

Ich habe lange gerätselt, ob ich mir einen Gerät mit Fax-Funktion kaufe. Aber meine liebe Schwester wies mich dann dezent darauf hin, das ich schon Hardware im Haus habe, welche dies kann :). Also ist nur ein Drucker mit Scanner draus geworden.


Was mir bisher unangehm aufgefallen ist; die Anleitung. Um den Scanner über die Druckerbedienung nutzen zu können, muß ein bestimmter Port der Firewall freigeben werden. Blöd ist nur, wenn in allen verfügbaren Anleitungen (Druck, Homepage, google) ein Zahlendreher vorkommt. Da half nur ein Blick in das Logfile der Firewall. So kann man auch Probleme schaffen, wo keine sein müssen.


Friday, December 01, 2006 12:09:16 PM (Mitteleuropäische Zeit, UTC+01:00) #
Comments [0]

Endlich habe ich es geschafft. Mein Blog ist online gegangen.

Zukünftig werde ich euch in unregelmäßigen Abständen mit hoch interessanten und wichtigen Neuigkeiten versorgen. Unter anderem aus den Themenbereichen:

  • Software-Entwicklung
  • Tools und Utilities
  • Gesellschaft
  • Privates ?