Prüfen ob eine Klasse ein bestimmtes Interface implementiert

Ab und an kann es vorkommen, dass man zur Laufzeit bestimmen muss, ob eine Klasse ein bestimmtes Interface implementiert. Dies läßt sich mit der Methode IsAssignableFrom() der Klasse System.Type realisieren:


public interface IMyInterface
{
    //Interface Code        
}

public class MyInterfaceImplementation : IMyInterface
{
    //Implementierung
}

public class AnotherClass
{ 
    //...
}

typeof(IMyInterface).IsAssignableFrom(typeof(AnotherClass)); //false
typeof(IMyInterface).IsAssignableFrom(typeof(MyInterfaceImplementation)); //true


Erweiterungsmethode: String.Like

Hier eine kleine Erweiterungsmethode, die ein SQL Like auf Strings ermöglicht:


public static bool Like( this string value, string pattern )
{
    string parsedPattern = "\\A" + Regex.Escape( pattern ).Replace( "\\*", ".*" ).Replace( "\\?", "." ) + "\\Z";

    Regex regex = new Regex(parsedPattern, RegexOptions.IgnoreCase);

    return regex.IsMatch(value);
}

Die Funktion eignet sich, wenn ich statt einer Linq-Abfrage einen Lamda-Ausdruck verwenden will/muss:


List<string> theSimpsons = new List<string>(){"Homer", "Bart", "Marge", "Lisa", "Maggie"};

Func<string, bool> matchCriteria = person => person.Like("*ar*");
Debug.WriteLine( "*ar*" );

foreach (string character in theSimpsons.Where(matchCriteria))
{
    Debug.WriteLine( character );
}

matchCriteria = person => person.Like( "M*i*" );
Debug.WriteLine( "M*i*" );
foreach( string character in theSimpsons.Where( matchCriteria ) )
{
    Debug.WriteLine( character );
}

matchCriteria = person => person.Like( "M*e" );
Debug.WriteLine( "M*e" );
foreach( string character in theSimpsons.Where( matchCriteria ) )
{
    Debug.WriteLine( character );
}

matchCriteria = person => person.Like( "*a*" );
Debug.WriteLine( "*a*" );
foreach( string character in theSimpsons.Where( matchCriteria ) )
{
    Debug.WriteLine( character );
}

matchCriteria = person => person.Like( "*a" );
Debug.WriteLine( "*a" );
foreach( string character in theSimpsons.Where( matchCriteria ) )
{
    Debug.WriteLine( character );
}


Ausgabe:
*ar*
Bart
Marge
M*i*
Maggie
M*e
Marge
Maggie
*a*
Bart
Marge
Lisa
Maggie
*a
Lisa

WHERE IN (…) Abfragen mit LINQ

Hier ein einfaches Beispiel, welches aus einer Liste von Büchern nur die Bücher von bestimmten Autoren findet:


List<Book> books = new List<Book>();
Book book;

book = new Book()
{
    Author = "Michael Moore",
    Title = "Stupid White Men",
    Price = 9.90M
};
books.Add(book);

book = new Book()
{
    Author = "Christian Nagel",
    Title = "C# 2008",
    Price = 59.99M
};
books.Add(book);

book = new Book()
{
    Author = "Robert C. Martin",
    Title = "Clean Code",
    Price = 19.90M
};
books.Add(book);

List<string> authorsToSearch = new List<string>(){"Michael Moore", "Robert C. Martin"};

books.Where(bookItem => authorsToSearch.Contains(bookItem.Author)).ToList().ForEach(Console.WriteLine);

Als Ausgabe erhält man hier nur die Bücher, deren Autor einem Author der Suchliste entspricht:

Michael Moore: Stupid White Men (9,90)
Robert C. Martin: Clean Code (19,90)

Ich habe in dem Beispiel den Where-Filter als Lambda eingesetzt, alternativ kann man die Suche natürlich auch direkt mit einer LINQ-Abfrage durchführen:


var booksFound = from bookItem in books
                        where authorsToSearch.Contains(bookItem.Author)
                        select bookItem;

Reflection und statische Klassen

Ich habe mich letztens mal mit dem Thema Reflection beschäftigt. Dabei kam zwangsläufig das Problem auf, dass ich irgendwie festellen musste, ob eine Klasse statisch ist oder nicht. Auf Nachfrage bei Google bin ich dann auf diesen Blogeintrag gestoßen, der sich mit genau diesem Problem beschäftigte:

http://dotneteers.net/blogs/divedeeper/archive/2008/08/04/QueryingStaticClasses.aspx

Windows Services: OnStart() debuggen

Einen Windows Service zu debuggen ist eigentlich recht einfach: Service starten, Visual Studio an den Prozess anhängen, fertig. Das funktioniert allerdings nicht ohne Weiteres bei der OnStart()-Methode, da diese beim Dienststart durchlaufen wird. Das Debugging kann hier auf zwei Arten erreicht werden:
1. Pausieren des Prozesses mittels Thread.Sleep()


        protected override void OnStart(string[] args)
        {
            Thread.Sleep(20000);
            Timer tTimer = new Timer(1000);
            tTimer.Elapsed += tTimer_Elapsed;
            tTimer.Start();
        }

2. Aufrufen des Debuggers mittels Debugger.Launch()


        protected override void OnStart(string[] args)
        {
            Debugger.Launch();
            Timer tTimer = new Timer(1000);
            tTimer.Elapsed += tTimer_Elapsed;
            tTimer.Start();
        }

Ich persönlich bevorzuge die 2. Methode, da man zum einen nicht erst warten muss, bis Thread.Sleep() beendet wird, zum anderen spart man sich das manuelle Anhängen an den Prozess. Der Aufruf von Debugger.Launch() sorgt dafür, dass man per Dialog eine neue Visual Studio Instanz öffnen kann, die dann zum Debuggen genutzt wird. Allerdings sollte man darauf achten, dass man den Aufruf nur dann tätigt, wenn man auch wirklich debuggen will. Dies kann beispielsweise per Kommandozeilenparameter durchgeführt werden.

Datentyp einer DataTable-Spalte ändern

Der Datentyp einer Spalte im DataTable lässt sich durch die DataType-Eigenschaft ermitteln oder festlegen.


DataTable t = new DataTable();
t.Columns.Add("Col1", typeof(string));
t.Columns["Col1"].DataType = typeof (Int32);

Allerdings ist das Setzen des Typs nur möglich, wenn das DataTable keine Daten enthält. Für ein gefülltes DataTable kann dies über ein zweites DataTable-Objekt, das per Clone() erstellt und mittels ImportRow() gefüllt wird, erreicht werden.


DataTable t = new DataTable();
t.Columns.Add("Col1", typeof (string));
for (int iCounter = 1; iCounter < 25; iCounter++)
{
  DataRow dRow = t.NewRow(); 
  dRow["Col1"] = iCounter.ToString();
  t.Rows.Add(dRow);
}
DataTable t2 = t.Clone();
t2.Columns["Col1"].DataType = typeof (Int32);
foreach (DataRow row in t.Rows)
{
  t2.ImportRow(row);
}

Mit C# Emails über Outlook senden

Für das Versenden einer Email über Outlook muss zunächst die Assembly “Microsoft.Office.Interop.Outlook” den Projektreferenzen hinzugefügt und der Namespace “Microsoft.Office.Interop.Outlook” per using-Direktive importiert werden. Der Rest ist dann ganz einfach.


using Microsoft.Office.Interop.Outlook;
namespace OutlookHelper
{
  public class Email
  {
    public static void SendMail(string sRecipient,
                                         string sCC,
                                         string sBCC,
                                         string sSubject,
                                         string sBody,
                                         param string[] sAttachment)
    {
      Application outlook = new Application();
      _MailItem mail = (_MailItem)outlook.CreateItem(OlItemType.olMailItem);

      mail.To      = sRecipient;
      mail.CC      = sCC;
      mail.BCC     = sBCC;
      mail.Subject = sSubject;
      mail.Body    = sBody;
      foreach (string _sAttachment in sAttachment)
      {
        mail.Attachments.Add(_sAttachment, OlAttachmentType.olByValue, 1, null) ;
      }

      mail.Send();

      mail    = null;
      outlook = null;
    }
  }
}