C# 9: Verbessertes “Pattern Matching”

Relational Patterns

Ab C# 9 können Werte mit Relational Patterns geprüft werden:

<kleiner als
>grösser als
<=kleiner oder gleich
>=grösser oder gleich

Dazu nun ein Code Beispiel:

using System;

namespace ConsoleApp2
{
    class Program
    {
        public class Animal
        {
            public string Name { get; set; }
            public int Weight { get; set; }
            public int YearOfBirth { get; set; }
        }

        static void Main(string[] args)
        {
            var animal = new Animal()
            {
                Name = "Tiger"
                ,Weight = 300
                ,YearOfBirth = 2016
            };

            if (animal is Animal { Weight: > 200 } animalWeightMoreThen200)
            {
                Console.WriteLine($"Animal is more then 200kg! " +
                    $"Weight: {animalWeightMoreThen200.Weight}kg");
            }
        }
    }
}

Wir haben ein Objekt Animal. Bevor wir mit diesem Objekt arbeiten, prüfen wir, ob es vom Typ Animal ist. Mit einem “Relational Pattern” können wir nun auch sicherstellen, dass unser Tier mehr als 200 kg wiegt, bevor wir damit arbeiten.

Pattern Combinators

Seit C# 9 haben wir nun auch die Möglichkeit mehrere Patterns zu kombinieren. Dazu haben wir folgende Möglichkeiten:

andund
oroder
notnicht

Dazu nun ein Code Beispiel:

using System;

namespace ConsoleApp2
{
    class Program
    {
        public class Animal
        {
            public string Name { get; set; }
            public int Weight { get; set; }
            public int YearOfBirth { get; set; }
        }

        static void Main(string[] args)
        {
            var animal = new Animal()
            {
                Name = "Tiger"
                , Weight = 299
                , YearOfBirth = 2016
            };

            if (animal is Animal { Weight: > 200 and < 300, 
                Name: "Tiger" } tigerWeighBetween200And300)
            {
                Console.WriteLine($"The tiger weight is between 200kg and 300kg! " +
                    $"Weight: {tigerWeighBetween200And300.Weight}kg");
            }
        }
    }
}

Wir haben ein Objekt Animal. Bevor wir mit diesem Objekt arbeiten, prüfen wir, ob es vom Typ Animal ist. Mit den kombinierten “Relational Patterns” können wir nun auch sicherstellen, dass unser Tier mehr als 200 kg und weniger als 300 kg wiegt und der Name Tiger ist, bevor wir damit arbeiten.

Nützliche Links

Microsoft docs: Pattern matching enhancements

C# 9.0: Improved Pattern Matching

Microsoft Learn

Mit der Webplattform Microsoft Learn bietet Microsoft viele verschiedene Module und Lernpfade (praktische Übungen), um sich mit den aktuellen Microsoft Technologien kostenlos weiterbilden zu können.

Das Einzige, was man dazu braucht, ist ein Microsoft Learn-Konto. Die Module sind versehen mit einem theoretischen und einem praktischen Teil, welcher dann mit der Hilfe einer Sandbox (Azure Shell mit allen benötigten Tools) durchgeführt werden kann.

Es gibt auch sogenannte “30 Days to Learn It-Herausforderungen”. Dabei werden mehrere Module zu einer Sammlung zusammen gefasst. Beispiel die “Cloud Skills Challenge – Azure Developer”. Sie besteht aus 35 Module, für die man laut Microsoft ca. 28 Std. und 16 Min. Zeit investieren muss. Beendet man die Herausforderung innerhalb dieser 30 Tage, erhält man eine 50% Gutschrift für ein “Microsoft Certification exam”.

Viel Spass beim Ausprobieren und Lernen! :o)

Nützliche Links

Microsoft Learn

30 Days to Learn It

Meine Badges & Trophäen

C# 9: Init only Properties / init only setters

Init only Properties sind unveränderbare Datenobjekte, die einmal initialisiert den Zustand nicht mehr ändern können. Dazu verwendet man das Schlüsselwort init anstelle von set.

// Auto property
public Guid MyId { get; init; }

// property
private Guid myId;
public Guid MyId{
  get {return myId;}
  init {myId = value;}
}

// lambda property
private Guid myId;
public Guid MyId{
  get  => myId;
  init => myId = value;
}

Wird nun die “MyId” einmal zugewiesen, kann diese nicht mehr versehentlich überschrieben werden. “MyId” kann nur bei der Objektinitialisierung oder über den Konstruktor festgelegt werden.

// object class with the secret 
public class MySecret
 {
  public MySecret()
  {
  }
  public MySecret(Guid myId)
  {
    MyId = myId;
  }
  public Guid MyId { get; init; }
}

// Example 1
// create an object with the secret
// assign with object initializer
MySecret mySecret = new MySecret()
{
  MyId = Guid.NewGuid()
};


// Example 2
// create an object with the secret
// assign in the instance constructor
MySecret mySecret2 = new MySecret(Guid.NewGuid());

Nützliche Links

docs.microsoft.com: init only setters

Azure: Attach debugger to App Service funktioniert nicht (Visual Studio 2019 V. 16.09.3)

Beim Versuch eine .NET 5 Webapplikation zu debuggen (Cloud Explorer -> App Service -> Attach Debugger) wurde mir immer folgende Meldung angezeigt:

Die Verbindung mit dem Remoteendpunkt wurde beendet.

Folgendes wurde überprüft:

  • Remotedebuggen ist aktiviert (App Service <Name> -> Konfiguration -> Allgemeine Einstellungen -> Debuggen)
  • Published wurde die “Debug” Konfiguration
  • Korrektes Target Framework eingestellt
  • App Service ist erreichbar

Ursache

Nach einer Weile recherchieren im Netz habe ich folgende Erkenntnis erlangt:

Visual Studio schickt eine Initialisierungsmeldung an den Remote Debugger. Im Inhalt sind unteranderem installierte Komponenten des VS. Es scheint, dass bei manchen VS Installationen diese Meldung die erwartete Grösse überschreitet, was dann zu einem sofortigen Abbruch führt. Gemäss Microsoft wurde dies bereits behoben im “App Service image Version 93” jedoch noch nicht weltweit verteilt. Was nun aber fortlaufen passieren soll. (24.02.2021)

Mit Hilfe von Kudu kann dies bei der Webapplikation überprüft werden. Cloud Explorer -> App Service <Name> -> Open in Kudu

Test halber habe ich einen neuen App Service-Plan mit Standort USA erstellt. Eine Testapplikation published und das Debuggen gestartet. Und es hat funktioniert. Der Azure App Service war in der Version:

Was ist nun die Lösung?

  1. Warten auf auf die “App Service image Version 93”
  2. Auf einen anderen Standort ausweichen, wenn möglich
  3. Als letzte Möglichkeit -> Als Workaround kann auch die Visual Studio Installation angepasst werden und nicht verwendete Komponenten deinstalliert werden (Habe ich selber nicht verifiziert)

Update (06.04.2021)

Das “App Service Image Version 93” ist jetzt auch an meinem verwendeten Standort angekommen und das Debuggen funktioniert wieder.

Nützliche Links

https://developercommunity.visualstudio.com/t/attach-debugger-to-azure-app-service-not-working/933126

.NET 6 Multi-platform App UI (MAUI)

Mit .NET 6 wird MAUI (Multi-platform App UI) xamarin.forms revolutionieren und die Entwicklung von “Cross-platform” Applikationen noch flexibler, produktiver und somit noch wirtschaftlicher ermöglichen.

Egal in welchem Umfeld werden bereits heute verschiedenste Plattformen (iOS, Android, Windows, Mac) eingesetzt, was zunehmend die Entwicklung von Applikationen erschwert. In vielen Betrieben wird auch das Thema BYOD (Bring Your Own Device) gefördert und sorgt dafür, dass die Plattform Vielfalt noch herausfordernder wird.

Das sind die Vorteile von .NET MAUI:

  • Free & open source
  • Cross-platform, native UI
  • Single project system, single codebase
  • Deploy to multiple devices, mobile & desktop
    • Native User Interfaces
    • Native API Access
    • Native Performance

Was heisst native UI?

Native UI heisst, egal welche Plattform ich als Benutzer verwende, ich erhalte immer die erwartete Oberfläche / Elemente (Datumspicker, Buttons, Navigation, Dark-Light Mode usw.) meiner verwendeten Plattform.

Video: The Future of Native Apps Development in .NET 6

Nützliche Links

Discord: DotNetEvolution

Xamarin

github: .NET MAUI

.NET 6.0 Preview Download

C#: Prüfen ob die Datenbankverbindung auf den SQL – Server verschlüsselt wird

Muss die Datenbankverbindung von einer C#-Applikation zum SQL-Server verschlüsselt werden, muss der SQL-Server mit einem Zertifikat korrekt konfiguriert sein. Im weiteren müssen im ConnenctionString Parameter konfiguriert werden, damit eine verschlüsselte Verbindung hergestellt wird. Dazu wird der ConnenctionString mit folgenden Parametern versehen:

  • encrypt=true SSL Encryption aktivieren.
  • trustServerCertificate=false Zertifikat wird validiert. (Bei self-signed Zertifikaten auf “true” setzen)

Wird nun mit der C#-Applikation eine Verbindung auf den SQL-Server hergestellt, sollte die Verbindung verschlüsselt sein. Wie kann man sich jedoch sicher sein? Eine Möglichkeit ist die Verwendung eines “Sniffers”, wie WireShark, oder aber man prüft dies auf dem SQL-Server selber.

Auf dem SQL-Server kann man folgende SQL-Abfrage absetzen, um alle Verbindungen mit ihren Verschlüsselungsoptionen anzuzeigen:


SELECT session_id,encrypt_option
FROM sys.dm_exec_connections

session_id  encrypt_option
----------- ----------------------------------------
73          TRUE
73          TRUE
73          TRUE
75          FALSE
76          FALSE

Bei den Verbindungen mit der SessionId 73 sehen wir, dass die Verschlüsselung aktiviert und verwendet wird. (encryption_option = true)

Nützliche Links

SQL Server SSL Troubleshooting Steps
Connection Properties
TrustServerCertificate Property

C# .NET: Erstellen einer COM-Komponente

COM-Komponenten können sowohl in Form von Laufzeitmodulen (DLL’s) als auch als ausführbare Programme implementiert werden. Damit die Funktionen der Komponente für den COM-Client sichtbar sind, müssen folgende Punkte befolgt werden:

  • Die Klasse muss „public“ sein
  • Properties, Methoden und Events müssen „public“ sein
  • Properties und Methoden müssen im Klassen-Interface definiert sein
  • Events müssen im Event-Interface definiert sein

Erstellen:

Projekteinstellungen
Projekteinstellungen

  1. Zuerst muss das COM-Interface definiert werden (Definition der Schnittstelle)
  2. Als zweiter Schritt muss die Klasse implementiert werden. Die Klasse muss den Namespace “InteropServices” importieren (using System.Runtime.InteropServices;)
  3. In den Projekteinstellungen unter „Erstellen“ muss die Option „Für COM-Interop registrieren“ sowie unter „Anwendung->Assemblyinformationen“ die Option „Assembly COM-sichtbar machen“ aktiviert werden
  4. Am Schluss muss das Assembly noch signiert werden. Dies kann in den Einstellungen unter “Signierung” gemacht werden. Dazu wird eine neue Schlüsseldatei erstellt

3. „Für COM-Interop registrieren“ Komponente lokal installieren
3. „Für COM-Interop registrieren“ Komponente lokal installieren
3. „Assembly COM-sichtbar machen“
3. „Assembly COM-sichtbar machen“
4. Assembly signieren
4. Assembly signieren


COM-Komponente registrieren:

Um die COM-Komponente auf einem anderen Gerät zu verwenden muss diese zuerst registriert werden. Dazu wird das Programm “RegAsm.exe” verwendet.


RegAsm.exe sCOMDemo.dll /codebase /tlb:sCOMDemo.tlb

COM-Komponente deregistrieren:

Bevor eine neue Version installiert wird, sollte die alte Version unregistriert werden.


RegAsm.exe sCOMDemo.dll /unregister

Beispiel Code:

Klassendiagramm
Klassendiagramm

Das Interface:



namespace sCOMDemo
{
    public interface IsCom
    {
        string helloWorld();
    }
}

Die Klasse:


using System.Runtime.InteropServices;

namespace sCOMDemo
{
    public class sCom:IsCom
    {
        public string helloWorld()
        {
            return "hello world!";
        }
    }
}

Verwendung der COM-Komponente unter VBScript:


Dim objDemo: set objDemo = createObject("sCOMDemo.sCom")
wscript.echo objDemo.HelloWorld()

wscript - Ausgabe
Nützliche Links:

Component Object Model (COM)
COM Interop Part 1: C# Client Tutorial
System.Runtime.InteropServices Namespace
How to: Create COM Wrappers
How to: Raise Events Handled by a COM Sink
Creating a COM Visible C# Component
Assembly Registration-Tool (Regasm.exe)
Wikipedia: COM

C#: XML-Serialisierung mit dem XmlSerializer Teil 3

In den vorhergehenden Beiträgen Teil 1 & Teil 2 haben wir eine Adressklasse erstellt um B2B- und B2C-Adressen zu speichern. Nun werden wir diese Adressklasse erweitern, damit auch Kommunikationsdetails (Telefon, Email, usw.) gespeichert werden können.

Als Erstes erstellen wir die Klasse “CommunicationDetail” um damit die Kommunikationsdetails zu speichern:


namespace XML_Serialisierung
{
    public class CommunicationDetail
    {
        public enum CommunicationDetailType
        {
            PRIVATE_MOBILE,
            BUSINESS_MOBILE,
            PRIVATE_PHONE,
            BUSINESS_PHONE,
            PRIVATE_FAX,
            BUSINESS_FAX,
            PRIVATE_EMAIL,
            BUSINESS_EMAIL,
            SKYPE_MESSANGER
        }

        [XmlAttribute("Typ")]
        public CommunicationDetailType DetailType { get; set; }

        [XmlElement("Wert")]
        public string Value { get; set; }

        public CommunicationDetail()
        {
        }
        public CommunicationDetail(CommunicationDetailType detailType, string value)
        {
            this.Value = value;
            this.DetailType = detailType;
        }
    }
}

Nun werden wir die Address-Klasse mit einer Liste vom Typ “CommunicationDetail” erweitern. Damit beim Serialisieren der Liste, die einzelnen Details auch richtig im XML-Abgebildet werden, verwenden wir das Attribut [XmlArray(“”)] um den Namen des Hauptelementes festzulegen und [XmlArrayItem(“”)] um damit den Namen der Unterknoten zu bestimmen.


namespace XML_Serialisierung
{
    public class Address
    {
        [XmlAttribute("Adressenummer")]
        public int AddressNumber { get; set; }
        
        [XmlElement("Strasse")]
        public string Street { get; set; }

        [XmlElement("Hausnumer")]
        public string HouseNumber { get; set; }

        [XmlElement("Land")]
        public string Country { get; set; }

        [XmlElement("Postleitzahl")]
        public string ZIP { get; set; }

        [XmlElement("Stadt")]
        public string City { get; set; }

        [XmlArray("Kommunikation")]
        [XmlArrayItem("Kommunikationsdetail")]
        public List CommunicationNumbers;


        public Address()
        {
            this.CommunicationNumbers = new List();
        }
    }
}

Klasse mit dem XmlSerializer serialisieren

Nun haben wir die Möglichkeit die Adresse mit Kommunikationsdetails zu erweitern:


/*b2c addresse*/
AddressB2C addressB2C_2 = new AddressB2C();
addressB2C_2.AddressNumber = 123456789;
addressB2C_2.Firstname = "Max";
addressB2C_2.Lastname = "Mustermann";
addressB2C_2.Street = "Musterstrasse";
addressB2C_2.HouseNumber = "77a";
addressB2C_2.City = "Musterhausen";
addressB2C_2.ZIP = "1234";
addressB2C_2.Country = "In einem fernen Land";

CommunicationDetail mobile = new CommunicationDetail(CommunicationDetail.CommunicationDetailType.PRIVATE_MOBILE, "079 123 45 67");
addressB2C_2.CommunicationNumbers.Add(mobile);

CommunicationDetail email = new CommunicationDetail(CommunicationDetail.CommunicationDetailType.PRIVATE_EMAIL, "meine@email.ch");
addressB2C_2.CommunicationNumbers.Add(email);

XmlSerializer xmls3 = new XmlSerializer(typeof(AddressB2C));
StreamWriter mwriter3 = new StreamWriter("b2cAddressWithNumbers.xml");
xmls3.Serialize(mwriter3, addressB2C_2);
mwriter3.Close();

Und als Ergebniss erhalten wir folgendes XML:




  
    
      079 123 45 67
    
    
      meine@email.ch
    
  
  Musterstrasse
  77a
  In einem fernen Land
  1234
  Musterhausen
  Max
  Mustermann

Nützliche Links:

C#: XML-Serialisierung mit dem XmlSerializer Teil 1
C#: XML-Serialisierung mit dem XmlSerializer Teil 2
msdn: xml.serialization
msdn: List

C#: XML-Serialisierung mit dem XmlSerializer Teil 2

Im vorhergehenden Beitrag haben wir aus einer einfachen Adressklasse eine XML-Datei generiert. In diesem Beitrag werden wir eine Kundenklasse erstellen, die entweder eine B2B- oder B2C-Adresse enthält und dann in eine XML-Datei geschrieben wird. Dazu erstellen wir zuerst eine Kundenklasse:


using System.Xml.Serialization;

namespace XML_Serialisierung
{
    [XmlRoot("Kunde")]
    public class Customer
    {
        [XmlAttribute("Kundennummer")]
        public int CustomerID { get; set; }

        [XmlElement("Adresse")]
        public Address CustomerAddress { get; set; }
        
        public Customer(bool b2c)
        {
            if (b2c == true)
            {
                this.CustomerAddress = new AddressB2C();
            }
            else
            {
                this.CustomerAddress = new AddressB2B();
            }
        }
        /*default constructor*/
        public Customer() {
            this.CustomerAddress = new AddressB2C();
        }
    }
}

Wird jetzt versucht diese Klasse zu serialiseren wird eine Exception geworfen:


System.InvalidOperationException wurde nicht behandelt.
  Message="Beim Generieren des XML-Dokuments ist ein Fehler aufgetreten."
  Source="System.Xml"
  StackTrace:
       bei System.Xml.Serialization.XmlSerializer.Serialize(XmlWriter xmlWriter, Object o, XmlSerializerNamespaces namespaces, String encodingStyle, String id)
       bei System.Xml.Serialization.XmlSerializer.Serialize(TextWriter textWriter, Object o)
       bei XML_Serialisierung.Program.Main(String[] args) in D:\data\Projects\intern\blog\src\XML-Serialisierung\Program.cs:Zeile 59.
       bei System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
       bei Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       bei System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       bei System.Threading.ThreadHelper.ThreadStart()
  InnerException: System.InvalidOperationException
       Message="Der Typ XML_Serialisierung.AddressB2B wurde nicht erwartet. Verwenden Sie das XmlInclude- oder das SoapInclude-Attribut, um Typen anzugeben, die nicht statisch sind."
       Source="uwky4mcz"
       StackTrace:
            bei Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterCustomer.Write2_Address(String n, String ns, Address o, Boolean isNullable, Boolean needType)
            bei Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterCustomer.Write3_Customer(String n, String ns, Customer o, Boolean isNullable, Boolean needType)
            bei Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterCustomer.Write4_Kunde(Object o)

Da das Property “CustomerAddress” vom Typ Address ist, beim serialisieren jedoch als Typ AddressB2B oder AddressB2C erscheint, weiss der XmlSerializer nicht, wie er diesen Datentyp verarbeiten soll. Damit der XmlSerializer damit korrekt umgehen kann, müssen wir ihn mit den möglichen Datentypen bekannt machen. Dazu wird das Attribut [XmlInclude(“”)] verwendet.


using System.Xml.Serialization;

namespace XML_Serialisierung
{
    [XmlInclude(typeof(AddressB2C))]
    [XmlInclude(typeof(AddressB2B))]

    [XmlRoot("Kunde")]
    public class Customer
    {
        [XmlAttribute("Kundennummer")]
        public int CustomerID { get; set; }

        [XmlElement("Adresse")]
        public Address CustomerAddress { get; set; }
        
        public Customer(bool b2c)
        {
            if (b2c == true)
            {
                this.CustomerAddress = new AddressB2C();
            }
            else
            {
                this.CustomerAddress = new AddressB2B();
            }
        }
        /*default constructor*/
        public Customer() {
            this.CustomerAddress = new AddressB2B();
        }
    }
}

Klasse mit dem XmlSerializer serialisieren

Starten wir nun nochmals einen Versuch, wird das Serialsieren funktionieren.


/*create a customer object*/
Customer customer = new Customer(false);
customer.CustomerID = 175;

AddressB2B b2bAddress = ((AddressB2B)(customer.CustomerAddress));
b2bAddress.AddressNumber = 123456789;
b2bAddress.CompanyName = "Muster AG";
b2bAddress.Division = "Musterkreation";
b2bAddress.Street  = "Musterstrasse";
b2bAddress.HouseNumber = "77a";

b2bAddress.City = "Musterhausen";
b2bAddress.ZIP = "1234";
b2bAddress.Country = "In einem Land";


XmlSerializer xmls2 = new XmlSerializer(typeof(Customer));
StreamWriter mwriter2 = new StreamWriter("CustomerWithb2bAddress.xml");
xmls2.Serialize(mwriter2, customer);
mwriter.Close();

Und als Ergebnis erhalten wir:




Musterstrasse
77a
In einem Land
1234
Musterhausen
Muster AG
Musterkreation




Nützliche Links:

C#: XML-Serialisierung mit dem XmlSerializer Teil 1
msdn: xml.serialization

C#: XML-Serialisierung mit dem XmlSerializer Teil 1

Mit dem XmlSerializer können auf einfache Weise XML-Dokumente erstellt werden. Zum Beispiel wollen wir eine XML-Datei mit Adressdaten generieren, die folgendermassen aussehen soll:




    Musterstrasse
    77a
    In einem Land
    1234
    Musterhausen
    Max
    Mustermann

Dazu erstellen wir zuerst einmal eine einfache Adressklasse, in der die Adressdaten gespeichert werden können:


namespace XML_Serialisierung
{
    public class Address
    {
        public int AddressNumber { get; set; }        
        public string Street { get; set; }
        public string HouseNumber { get; set; }
        public string Country { get; set; }
        public string ZIP { get; set; }
        public string City { get; set; }
    }
}

Würden man diese Klasse jetzt serialisieren, hätten die XML-Tags nicht die gewünschten Namen. Der XmlSerializer würde die Namen der Properties verwenden.

Mit Hilfe von Attributen kann man die Ausgabe der XML-Datei steuern. Im obigen XML ist die Adressnummer ein Attribut des Wurzelelment Adresse. Um dies zu erreichen, wird das Attribut [XmlAttribute] verwendet. Das Attribut [XmlElement(“”)] wird verwendet um den Namen des XML-Tag festzulegen.


using System.Xml.Serialization;

namespace XML_Serialisierung
{
    public class Address
    {
        [XmlAttribute("Adressenummer")]
        public int AddressNumber { get; set; }
        
        [XmlElement("Strasse")]
        public string Street { get; set; }

        [XmlElement("Hausnumer")]
        public string HouseNumber { get; set; }

        [XmlElement("Land")]
        public string Country { get; set; }

        [XmlElement("Postleitzahl")]
        public string ZIP { get; set; }

        [XmlElement("Stadt")]
        public string City { get; set; }
    }
}

In unserer Adressklasse fehlen uns aber noch ein paar Angaben wie Name, Vorname, Firmenname.. usw. Dazu werden wir 2 neue Klassen erstellen. Eine Klasse für Firmenadressen (B2B) und Privatadressen (B2C).


using System.Xml.Serialization;

namespace XML_Serialisierung
{
    [XmlRoot("Adresse")]
    public class AddressB2C: Address
    {
        [XmlElement("Vorname")]
        public string Firstname { get; set; }

        [XmlElement("Nachname")]
        public string Lastname { get; set; }
    }
}

Das Attribut [XmlRoot(“”)] wird verwendet um den Namen des Wurzelelements (Rootelement) festzulegen.


using System.Xml.Serialization;

namespace XML_Serialisierung
{
    [XmlRoot("Adresse")]
    public class AddressB2B:Address
    {
        [XmlElement("Firmenname")]
        public string CompanyName { get; set; }

        [XmlElement("Abteilung")]
        public string Division { get; set; }

        [XmlElement("Kontaktperson")]
        public string ContactPerson { get; set; }
    }
}

Klasse mit dem XmlSerializer serialisieren

Das serialisieren der erstellten Adressklassen kann nun mit sehr wenig Code-Zeilen erledigt werden.
Dazu wird zuerst das gewünschte Objekt AddressB2B oder AddressB2C erstellt und dann die Werte zugewiesen. Damit der XmlSerializer den Typ der zu serialsierenden Klasse kennt, muss dieser beim Instanziieren des XmlSerializer mitgegeben werden.


/*********************************************************/
//example 1
/*********************************************************/
/*b2c addresse*/
AddressB2C addressB2C = new AddressB2C();
addressB2C.AddressNumber = 123456789;
addressB2C.Firstname    = "Max";
addressB2C.Lastname     = "Mustermann";
addressB2C.Address1     = "Musterstrasse";
addressB2C.HouseNumber  = "77a";
addressB2C.City         = "Musterhausen";
addressB2C.ZIP          = "1234";
addressB2C.Country      = "In einem Land";

/*Create a XmlSerializer from type AddressB2C*/
XmlSerializer xmls = new XmlSerializer(typeof(AddressB2C));
StreamWriter mwriter = new StreamWriter("b2cAddress.xml");
xmls.Serialize(mwriter, addressB2C);
mwriter.Close();

Als Ergebnis erhalten wir in der Datei “b2cAddress.xml” die gewünschte XML-Struktur.

Nützliche Links:

msdn: xml.serialization
C#: XML-Serialisierung mit dem XmlSerializer Teil 2