Bernhard 的个人资料Bernhard Grojer - Blog照片日志列表 工具 帮助

日志


9月16日

System.Reflection, Properties mit einem bestimmten Typ schreiben


Angenommen man möchte alle Properties eines Objektes auf true oder false setzen:

Zuerst müssen wir uns alle schreibbaren Properties vom Objekt holen um diese verändern zu können.

var c = new Customer();

var propInfos = c.GetType().GetProperties().Where(p => p.CanWrite && p.PropertyType.IsAssignableFrom(typeof(bool)));
foreach (var pi in propInfos)
{
        var t = pi.PropertyType;
        pi.SetValue(c, true, null);
}

Die Klasse Customer ist hierbei wie folgt definiert:

public class Customer
{
        public string FirstName { get; set; }
        public bool Active { get; set; }
        public bool? IsNew { get; set; }
}

Active, und IsNew würden in diesem Fall auf true gesetzt werden. FirstName wird ausgelassen.

Geht übrigens auch noch kürzer:

var c = new Customer();    
c.GetType().GetProperties().Where(p => p.CanWrite && p.PropertyType
.IsAssignableFrom(typeof(bool))).ToList().ForEach(p => p.SetValue(c, true, null));

5月31日

Windows Azure, Visual Studio 2010, Class Library (Klassen Biblioteken)

Scheinbar gibt es unter Visual Studio 2010 bzw. den Windows Azure Templates ein Problem mit zusätzlichen "Projekten" in der Windows Azure Solution.

Fügt man eine neue (leere) Class Library zum Projekt hinzu und setzt Referenzen auf das Projekt kann man das Projekt nicht mehr bauen:


Error 1 The OutputPath property is not set for this project.  Please check to make sure that you have specified a valid Configuration/Platform combination.  Configuration='Debug'  Platform='AnyCPU' C:\Windows\Microsoft.NET\Framework\v4.0.20506\Microsoft.Common.targets 582 10 ServiceState

Es hat sich danach rausgestellt, dass scheinbar in der Class Library (Klassen Bibliothek) nur Build-Einstellungen für x86 verfügbar sind. Dies dürfte das eigentliche Problem auslösen:


Ich habe keine Möglichkeit gefunden dies in Visual Studio 2010 direkt zu ändern. Daher habe ich (manuel) die Projekt-Datei der Class Library bearbeitet:

Die Visual C# Project file (.csproj) - original (nur x86 Build):
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
    <ProductVersion>10.0.20506</ProductVersion>
    <SchemaVersion>2.0</SchemaVersion>
    <ProjectGuid>{C4DA9B13-3879-4F55-8510-DE795CD4E9BE}</ProjectGuid>
    <OutputType>Library</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>ServiceStateLib</RootNamespace>
    <AssemblyName>ServiceStateLib</AssemblyName>
    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
    <FileAlignment>512</FileAlignment>
    <PlatformTarget>x86</PlatformTarget>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>bin\Debug\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
    <PlatformTarget>AnyCPU</PlatformTarget>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\Release\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
...

Geändert auf (AnyCPU):
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProductVersion>10.0.20506</ProductVersion>
    <SchemaVersion>2.0</SchemaVersion>
    <ProjectGuid>C4DA9B13-3879-4F55-8510-DE795CD4E9BE}</ProjectGuid>
    <OutputType>Library</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>ServiceStateLib</RootNamespace>
    <AssemblyName>ServiceStateLib</AssemblyName>
    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
    <FileAlignment>512</FileAlignment>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>bin\Debug\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\Release\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
...


Danach neue einbinden und alles läuft wunderbar.

Windows Azure - Visual Studio 2010

Für Visual Studio 2010 gibt es seit kurzem das Windows Azure May CTP. Damit bekommt man nun auch Unterstüzung für VS 2010 und die passenden "Cloud Templates".

Wahrlich hat man f. VS 2010 keine wirkliche Vorteile durchs neue Framework bei der Azure Entwicklung da .net 4.0 im Moment NICHT unterstützt ist unter Windows Azure.

Da Visual Studio 2010 allerdings Multi-Targeting unterstützt können .net 3.5 SP1 Anwendung ohne Probleme erzeugt werden.

5月18日

Visual Studio 2010 - Beta1 (via MSDN)


Visual Studio 2010 Beta 1 soll ab heute in via MSDN verfügbar sein!

Im Moment ist noch nichts online (Stichwort Zeitverschiebung)
12月4日

Windows Live SkyDrive – 25 GB gratis


Seit kurzem gibts beim Windows Live SkyDrive 25 GB kostenlos pro Live ID.

Auch sonst gibts jede Menge Änderungen. Mehr Informationen gibts im SkyDrive Team Blog.

10月10日

.net 4.0 & Visual Studio 2010

Das .net 4.0 sowieso Visual Studio 2010 bereits angekündigt wurden habe ich schon vor kurzem gebloggt.

In der Zwischenzeit gibts bereits jetzt mehr Informationen dazu hier.

LINQ Provider - Vom Ausdruck zum Ergebnis - Teil 3


Teil 3 von der Blog-Serie zum Thema LINQ Provider.
Bevor Sie hier weiterleisen
sollten Teil 1 und Teil 2 gelesen haben.

Nachdem wir im Teil 2 unsere Query<T> Klasse implementiert haben stehen wir nun vor unserem letzten Problem: den eigentlichen Provider für die Datenquelle

Dieser muss:

- die Abfrage in möglichst optimierter Form f. d. Datenquelle entsprechend umwandeln
- das Ergebnis von der Datenquelle in die (Ziel-)Objekte wandeln und retournieren.

Genau dafür haben wir bereits vorab die Idee geboren eine entsprechende Provider-Basisklasse zu erstellen, um später nur noch die die eigentliche Logik - Provider.Execute(…) – umzusetzen zu müssen.

Daher implementieren wir im Provider die Funktionalität um eine Instanz von Query<T> zu bilden und diese zu retournieren (CreateQuery<>()).
Ein nicht generischer Aufruf ist hier im Moment nicht implementiert.

public abstract class QueryProvider : IQueryProvider
    {

        #region IQueryProvider Members

        public IQueryable<T> CreateQuery<T>(Expression expression)
        {
            return new Query<T>(this, expression);
        }

        public IQueryable CreateQuery(Expression expression)
        {
            throw new NotImplementedException();
        }

        T IQueryProvider.Execute<T>(Expression expression)
        {
            return (T)this.Execute(expression);
        }

        object IQueryProvider.Execute(Expression expression)
        {
            return this.Execute(expression);
        }

        #endregion

        public abstract object Execute(Expression expression);
    }

In der Basisklasse erzeugen wir außerdem eine abstrakte Methode “Execute” die unser eigentlicher Provider später implementieren muss.
Die vom IQueryProvider Interface stammenden .Execute<T> Methoden rufen diese auf und reichen das Ergebnis weiter.

Somit haben wir bereits mehr als nur einen Grundstein gelegt und können nun verschiedene Provider on-top umsetzen und abfragen auf beliebige Datenquellen ermöglichen.

public class MyCustomProvider : QueryProvider
{
        public override object Execute(Expression expression)
        {
           //Execute Query, Create return Value(s)
        }
}

Im vierten Teil der Serie werden wir uns eine Linq.Abfrage bereit legen und die Execute Methode in unsere konkrete Providerklasse implementieren.

Sie möchten mehr wissen zum Thema? Auf der ADC08 gibt es eine Session von mir:

10月7日

LINQ Provider - Vom Ausdruck zum Ergebnis - Teil 2


Teil 2 von der Blog-Serie zum Thema LINQ Provider.
Bevor Sie hier weiterleisen sollten
Teil 1 gelesen haben.


Im ersten Teil haben wir bereits Basistechnologien abgesteckt und die Hintergründe schon etwas umschifft.
Wir sind weiteres dazu übergegangen uns mit 2 Basisklassen auseinanderzusetzen.

Auf der einen Seite haben wir uns dafür Query<T> bereit gestellt, die die eigentliche “Ergebnismenge” in Zukunft repräsentieren soll.
zB eine Liste von Kunden, Mitarbeitern, Produkten usw. usf.
Auf der anderen Seite hatten wir noch den QueryProvider, der den eigentlichen Gang zur Datenquelle, anhand der Basis-Interaces erstellt.

Zuerst beginnen wir nun die Funktionalitäten in Query<T> umzusetzen:

Hierfür wird es allerdings notwendig, dass wir eine Instanz unseres QueryProvider in dieser Klasse halten können und weiteres einen entsprechenden Konstrukter bereitstellen, der einen QueryProvider sowie optional einen ExpressionTree von LINQ entgegennimmt.
Wurde uns durch LINQ kein entsprechender ExpressionTree weitergegeben erzeugen wir uns eine ConstantExpression die unsere Ergebnismenge nicht weiter einschränkt.

public class Query<T> : IOrderedQueryable<T>, IQueryable, IOrderedQueryable
    {
        QueryProvider _Provider;
        Expression _Expression;

        public Query(QueryProvider provider)
        {
            this._Provider = provider;
            this._Expression = Expression.Constant(this);
        }

        public Query(QueryProvider provider, Expression expression)
            : this(provider)
        {
            this._Expression = expression;
        }

       //Implementierung der Interfaces ...
    }

Bei der Implementierung des Interfaces machen wir nun nichts anderes als “jeweils” Provider.Execute(…) aufzurufen und diesen unsere Expression weitergereicht.
Die Auswertung und auch der Gang zur Datenquelle obliegt nun unserem Provider.

    public class Query<T> : IOrderedQueryable<T>, IQueryable, IOrderedQueryable
    {
       //...

        public IEnumerator<T> GetEnumerator()
        {
            var r = this.Provider.Execute<IEnumerable<T>>(this._Expression) as IEnumerable<T>;
            return r.GetEnumerator();
        }
        IEnumerator IEnumerable.GetEnumerator()
        {
            var r = this.Provider.Execute(this._Expression) as IEnumerable;
            return r.GetEnumerator();
        }
  
       //...
     }

Und somit sind wir nun auch einem Geheimnis von LINQ auf die Schliche gekommen, weshalb Abfragen üblicherweise erst bei Zugriff ausgeführt werden.
Den Erst das Triggern von GetEnumerator() ruft die Execute Methode unseres Providers auf.

Unsere nächste Aufgabe wird somit ein Umsetzung unserer Provider-Basisklasse werden. Mehr dazu jedoch im 3ten Teil.

Sie möchten mehr wissen zum Thema? Auf der ADC08 gibt es eine Session von mir:

10月3日

ADO.net DataServices


Mit dem Release vom .net Framework 3.5 SP1 (böse Zungen sagen auch .net 3.6 dazu) haben wir eine relativ einfache Möglichkeit bekommen, um Daten über eine HTTP Schnittstelle bereitzustellen.

Was müssen wir dafür tun?

1) Erstellen einer neuen ASP.net Web Application

image

2) Ein ADO.net Entity Data Model erstellen (*.edmx)

3) Ein ADO.net Data Service hinzufügen und adaptieren.

Imports System.Data.Services
Imports System.Linq
Imports System.ServiceModel.Web

Public Class Northwind
    ' TODO: replace [[class name]] with your data class name
    Inherits DataService(Of NorthwindEntities)

    ' This method is called only once to initialize service-wide policies.
    Public Shared Sub InitializeService(ByVal config As IDataServiceConfiguration)
        ' TODO: set rules to indicate which entity sets and service operations are visible, updatable, etc.
        ' Examples:
        ' config.SetEntitySetAccessRule("MyEntityset", EntitySetRights.AllRead)
        ' config.SetServiceOperationAccessRule("MyServiceOperation", ServiceOperationRights.All)

        config.SetEntitySetAccessRule("*", EntitySetRights.All)

    End Sub

End Class

Achtung das ADO.net DataService muss hierbei vom Context abgeleitet werden.

4) Testen des Services. –> F5 sollte hierfür reichen.

Im Firefox wirds sofort klappen.
Im Internet-Explorer (zumindest IE 8 Beta 2) vermutlich nicht.
http://127.0.0.1:49338/Northwind.svc/ <- Im IE muss nämlich der letzte Schrägstrich noch manuell dran gemacht werden damits läuft.

image

Im einem zukünftigen Eintrag wollen wir das soeben erstellte Service noch konsumieren.

Fragen dazu? Kommentar posten ;)

9月24日

LINQ Provider - Vom Ausdruck zum Ergebnis - Teil 1


SQL Server, Webservice, WCF, Dateisystem, CSV Dateien, XML, Logs, ...

... überall Daten. Zugreifen? Mal so mal so. Immer andere Technologien erlernen um an die Daten ranzukommen.

Alternativen? Natürlich!: LINQ Provider.

Was müssen wir dafür tun? Eigentlich eine zentrale Stelle anfassen ...

ProviderModel 

... um zwischen der LINQ Engine und dem Datenspeicher unsere Logik implementieren. Doch leider ist die Aufgabe nicht ganz trivial und zwingt uns einige Tasks zu erledigen.

Dafür müssen wir zuerst abstecken welche Aufgaben wir zu erledigen sowie welche Voraussetzungen wir habe:

  • API für den Datenzugriff
  • Klasse für Abfrage: IQueryable<T> (oder IOrderedQueryable<T>, dass IQueryable<T> implementiert)
  • Klasse für den Provider: IQueryProvider
  • Datencontext erstellen der uns Strongly-Typed Zugriff auf die Datenquelle erlaubt.
Einen Teil der Funktionalität können wir in Basisklassen ablegen.
public class Query<T>: IOrderedQueryable<T>, IQueryable,IOrderedQueryable 
    {
        QueryProvider _Provider;
        Expression _Expression;
    }
public abstract class QueryProvider : IQueryProvider
    {
    }

Query<T> bietet uns somit bereits eine generische Basis für die weitere Implementierung unserer Datenquellen.
Die QueryProvider Basisklassen erlaubt uns die Implementierung für das parsen und erstellen d. Abfrage, sowie das Weiterreichen für die Ausführung vorzunehmen.

Basierend auf dieser Grundfunktionalität können wir nun unsere eigentliche Aufgabestellung umsetzen. Mehr dazu jedoch im 2ten Teil. Stay tuned.

Sie möchten mehr wissen zum Thema? Auf der ADC08 gibt es eine Session von mir:

ADCTeaser

8月7日

.net Framework 3.5 SP1 - RTM


Mit dem SQL Server 2008 haben wir auch das SP1 für .net Framework 3.5 (Link im Moment noch beta) bekommen.

Doch leider fehlt uns noch Visual Studio 2008 SP1 damit wir SQL Server 2008 neben Visual Studio 2008 installieren können.

Dies soll sich allerdings am Montag ändern. SP1 soll am 11. August 08 inkl. EntityFramework via MSDN verfügbar werden.

7月18日

Parallel Extensions - June 2008 CTP


In der Zwischenzeit tut sich bei der Leistung die eine einzige CPU bringt leider nur mehr sehr wenig. Allerdings bekommen wir immer Mehr CPU(Kerne) die unsere Aufgaben erledigen können.

Doch - Sie wissen das sicherlich schon - ist Mutlithreading in der eigenen Anwendung immer ein Aufwand und oftmals nicht so einfach umsetzbar.

Microsoft arbeitet allerdings seit einiger Zeit an den Prallel Extensions für das .net Framework 3.5. Im Moment haben wir die June 2008 CTP verfügbar.

Ich wollte die Sache daher gleich mal testen. Und zwar wollte ich alle Primzahlen in einen gewissen Zahlenbereich berechnen lassen (brute-force)

   1:          public List<int> GetPrimeNumbers(int lowerLimit, int upperLimit)
   2:          {
   3:              var lst = new List<int>();
   4:              for (int i = lowerLimit; i < upperLimit; i++)
   5:              {
   6:                  if (IsPrime(i))
   7:                      lst.Add(i);
   8:              }
   9:              return lst;
  10:          }
  11:   
  12:          public bool IsPrime(int n)
  13:          {
  14:              for (int i = 2; i < n; i++)
  15:              {
  16:                  if (n % i == 0)
  17:                      return false;
  18:              }
  19:              return true;
  20:          }

Die Funktion GetPrimeNumbers gibt daraufhin alle Primzahlen retour. Allerdings - welche Überraschung - wird die Sache nur auf einen Kern ausgeführt. WIr verschenken daher auf Dual Cores bereits 50% Leistung.

Also versuchen wir das Problem zu umschiffen und Fügen folgende Methode hinzu:

   1:          public List<int> GetPrimeNumbersParallel(int lowerLimit, int upperLimit)
   2:          {
   3:              var lst = new List<int>();
   4:              Parallel.For(lowerLimit, upperLimit, delegate(int i)
   5:                              {
   6:                                  if (IsPrime(i))
   7:                                      lst.Add(i); 
   8:                              }
   9:                          );
  10:   
  11:              return lst;
  12:          }

In Zeile 4 verwenden wir nun die Prallel.For Methode (System.Threading) der Parallel Extensions und somit haben wir einen Methode entwickelt die all unsere Kerne nutzt ohne uns zu (manuellen) Threading zu zwingen.

Nun zu unserem Aufruf:

   1:              Stopwatch sw;
   2:              var pn = new PrimeNumber();
   3:              var startNumber = 2;
   4:              var endNumber = 500000;
   5:   
   6:              sw = Stopwatch.StartNew();
   7:              var res1 = pn.GetPrimeNumbers(startNumber, endNumber);
   8:              Console.WriteLine("Done Seq: {0}", sw.ElapsedMilliseconds);
   9:   
  10:              sw = Stopwatch.StartNew();
  11:              var res2 = pn.GetPrimeNumbersParallel(startNumber, endNumber);
  12:              Console.WriteLine("Done Parallel: {0}", sw.ElapsedMilliseconds);

Wir müssen beim Aufruf selbst nichts mehr beachten.


PrimeNumberResult 

Das Ergebnis kann sich sehen lassen würde ich sagen.

Download des Samples gibts hier.

7月15日

C# 4.0

Erstes Infos vom Team zu C# 4.0 gibts auf Channel9.

Anders Hejlsberg (Wer? Sie wissen schon: Pascal, Delphi, C#, LINQ, ... - irgendwer muss sich das ja ausgedacht haben) und der Rest vom C# Team erzählen ein bisschen über die Zeile die Microsoft für C# 4.0 hat.

Eventull wird es nun doch noch etwas Yoda Syntax.

5月13日

.net Framework 3.5 - Beta1


Ihr dachtet die stressigen Tage sind vorbei? .net 3.5 Release und es wird ruhiger?

Schwer getäuscht,- .net Framework 3.5 SP1 Beta1 ist hier mit vielen Änderungen ...

Scott Guthrie (wer auch sonst) hat die wichtigsten Information zusammengestellt.