Alex Hoffman

Perspective on development, management and technology

Syndication

News

    Subscribe

    IASA Member

August 2007 - Posts

Quote of the Week

"All too often, customers and managers don't know what they want until they don't get it."


Hitchhiker's Guide to Visual Studio and SQL Server, 7th Edition: Best Practice Architectures and Examples (Amazon)
R. Vaughn William, Peter Blackburn
Addison Wesley Professional

Posted Friday, August 31, 2007 2:50 PM by Alex Hoffman | with no comments

CodeDomProvider - Targeting .Net 3.5

If your using a CodeDomProvider to compile code yourself programmatically in VS 2008, what version of the Framework is targeted?

By default it is 2.0, irrespective of which VS 2008 target version (2.0, 3.0 or 3.5) is specified.

In order to target the 3.5 framework, provide an IDictionary<string,string> instance in the provider's constructor as shown below:-  

    var providerOptions = new Dictionary<string,string>();
providerOptions.Add("CompilerVersion", "v3.5");

CodeDomProvider compiler = new CSharpCodeProvider(providerOptions); // C# example
compiler = new VBCodeProvider(providerOptions); // VB example 

Note that the dictionary contains an entry "CompilerVersion", "v3.5".

For C#, this is represented as something like the following in ASP.NET, and is what VS 2008 b2 inserts for you into the web.config file of each web app. 

  <system.codedom>
<
compilers>
<
compiler language="c#;cs;csharp" extension=".cs"
compilerOptions="/warnaserror-" warningLevel="4"
type="Microsoft.CSharp.CSharpCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<
providerOption name="CompilerVersion" value="v3.5"/>
</
compiler>
</
compilers>
</
system.codedom>

Posted Wednesday, August 29, 2007 3:15 PM by Alex Hoffman | with no comments

Filed under: , ,

Adventures in .NET 3.5 Part 4

This is the 4th part in a series.  See Part1, Part 2 and Part3.

 
Extension Methods continued 

So, where we left things last time, was with the creation of a Transform() extension method that allowed us to output to the console, lowercase states transformed from uppercase ...

     new[] { "NSW", "WA", "QLD", "SA", "TAS", "VIC" }
       .Transform( s => s.ToLower() )
       .Concatenate(", ")
       .Print("States: ");       // outputs... States: nsw, wa, qld, sa, tas, vic

Or to just to get back a new collection ...

     var lowerstates = new[] { "NSW", "WA", "QLD", "SA", "TAS", "VIC" }.Transform( s => s.ToLower() ); 

But, the way I've implemented the Transform() method, we can't change the type of resulting collection - something I want to do.

For example, I'd like to be able to create a new collection with the lengths of the state names as ints instead of strings.  Or given some dates, I'd like to be able to get back a collection of the day names of each date as strings.

Also, I'm not too happy with the method name Transform().  We have previously created an extension method named Each() that takes an Action() delegate.  Lets, overload Each() so that we have just one method name to remember.  The following extension method will give me what I need ...

     public static IEnumerable<TResult> Each<T, TResult>(this IEnumerable<T> items, Func<T, TResult> function)
     {
         foreach (var item in items)
         {
             yield return function(item);
         }
     }

While it looks nasty, all one has to remember is how to use it.

We can now type as before ...

     var lowerstates = new[] { "NSW", "WA", "QLD", "SA", "TAS", "VIC" }.Each( s => s.ToLower() );

or

     new[] { "NSW", "WA", "QLD", "SA", "TAS", "VIC" }
       .Each( s => s.ToLower() )
       .Concatenate(", ")
       .Print("States: ");       // outputs... States: nsw, wa, qld, sa, tas, vic

But we can also do the following to convert the following strings to decimals ... 

     new[] { "1.34", "3.79" }
         .Each<string, decimal>( i => Convert.ToDecimal(i) )
          .Concatenate(", ")
         .Print("Decimals as Strings: ");     // outputs... Decimals as Strings: 1.34, 3.79

 
 The Each() method above specifies the Type to convert from, and the Type to convert to, and the lambda performs the conversion.

 As another example, consider the following ...

      new[] { "jan 1 2002", "Aug 17 2007", "Feb 18 2045" }
         .Each<string, DateTime>( i => DateTime.Parse(i) )
         .Each<DateTime, DayOfWeek>( i => i.DayOfWeek )
         .Concatenate(" to ")
         .Print("Days: ");                    //outputs... Days: Tuesday to Friday to Saturday

Here, the first Each() method parses each date string and converts it to a DateTime, then the second converts the DateTime to a DayofWeek enum which is then output to the console.  One can string together multiple Each() methods, each modifying or acting on the collection contents.

And as before, one can still have Each() perform an action ...

     new[] { 1, 2, 3, 4 }.Each( i => i.Print() );
 

I'll tidy up, add exception handling and publish the code for all this shortly.

Posted Tuesday, August 7, 2007 11:21 AM by Alex Hoffman | 2 comment(s)

Filed under: , ,

Adventures in .NET 3.5 Part 3

This is the 3rd part in a series.  See Part1 and Part 2

 
Inferring a Collection Type

In C# 3.5, the compiler can (typically) infer the type of a collection.  The member type doesn't need to be explicitly specified.

     var nums = new[] { 1,2,3 };
 or
     var states = new[] { "NSW", "WA", "QLD", "SA", "TAS", "VIC" } ;
 
We could now apply the Concatenate and Print extension methods from Part 1, in order to create an array, and output it to the console in a single line ...

     new[] { 1,2,3,4,5 }.Concatenate().Print();       // displays: 12345
 

Transforming the Collection

What I'd now like to do, is be able to easily transform the collection. For example, using the "states" array declared earlier, I'd like to be able to say something like...

     var lowerStates = states.Transform( s => s.ToLower() );

Or, double each of those "nums" ...

     var doubled  = nums.Transform( n = > n *= 2 );

Out of the box I haven't been able to do that.  Sure you could use the Array.ConvertAll() method, but that doesn't provide the neat syntax I'm after.

So what to do?  The Each() extension method I created in the previous post won't work either, because it simply accepts an Action delegate that returns void.  The framework Predicate delegate doesn't help either because it returns a bool

3.5 introduces a general Func() delegate that we might use later, but for now what we really need is a delegate of T that returns T, so I'll create one.

     public delegate T Transformation<T>(T obj);

Now that we have that, we can create an extension method that meets our needs ...

     public static IEnumerable<T> Transform<T>(this IEnumerable<T> items, Transformation<T> transform)
     {         
         foreach (var item in items)
         {
             yield return transform(item);
         }
     }


Let's convert those states to lowercase, and as before apply the Concatenate() and Print() methods to output lowercase states to the console

     states.Transform( s => s.ToLower() )
       .Concatenate(", ")
       .Print("States: ");       // outputs "States: nsw, wa, qld, sa, tas, vic"


I haven't touched on LINQ yet, but it introduces a new standard query syntax.  We can use some of the extension methods built in to the framework to support it to further enhance our previous statement.  Note the framework Where() and OrderByDescending() extension methods below.  Any guesses as to the output?

     states.Transform( s => s.ToLower() )
       .Where( i => i.Contains("w") )
       .OrderByDescending( i => i )
       .Concatenate(", ")
       .Print("States: ");       // outputs ?


The Transform method returns an IEnumerable of T, where T is the same type as the initial collection.  So one cannot (as implemented) convert a collection of state names to a collection of another type - say integers that represent the lengths of the names.  Wouldn't it be good if we could do that as well?

Posted Monday, August 6, 2007 2:36 PM by Alex Hoffman | 4 comment(s)

Filed under: , ,

Adventures in .NET 3.5 Part 2 - Ruby Blocks

In my previous post, I talked about .NET 3.5 Extension Methods and ended by mentioning Ruby Blocks - because they are much admired.  As one example in Ruby, one might output the sum of an array of numbers as follows ...

      list = [1,2,3,4,5,6,7,8,9,10]
      sum = 0
      list.each() {|i| sum = sum + i}
      puts sum

What is now possible in .NET 3.5?  Well, one could write the following C# code ...

      int[] list = {1,2,3,4,5,6,7,8,9,10};
      var sum = 0;
      list.Each(i => sum += i);
      sum.Print();      // an extension method from my previous post

How is the "Each" method above implemented?  As an Extension method as follows ...

      public static void Each<T>(this IEnumerable<T> items, Action<T> action) {
          foreach (var item in items)
          {
              action(item);
          }
      }

One could use this Extension Method to apply any statement against each item in a collection.  For example, I could now output each item to the console with the following statement ...

      list.Each(i => i.Print());

For me, this is a slightly better syntax in this circumstance than the built in Array.ForEach<T> method which also takes an Action<T> as a parameter.
In other words, I prefer writing list.Each(i => sum += i); instead of  Array.ForEach(sports, i => sum += i);

Posted Saturday, August 4, 2007 7:11 PM by Alex Hoffman | 3 comment(s)

Filed under: , ,

Adventures in .NET 3.5 Part 1

A "Print" To the Console

Because I write a lot of small console applications, I find myself typing ...

        Console.WriteLine("some text"); 

in C# again and again.  I've always pined for the ability to simply be able to have an object "Print" itself to the console.

In other words, I'd really like to be able to type statements like those below ...

      87.Print();
      "alex".Print();
      DateTime.Now.Print();
      typeof(int).Print();

Well .NET 3.5 makes that easy with Extension Methods.  Check out this post to get started.  The code to implement such a "Print" method is simple ... 

      public static void Print(this object o) {
          Console.WriteLine(o);
      }


 

Concatenation

Another thing I need to do all the time is output the contents of a collection as a string on a single line with a definable separator.  Now that we have a "Print" method, I'd like to be able to type ...

      /* output to the console: Soccer,Rugby,Tennis,Cricket */
      var sports = new string[] { "Soccer", "Rugby", "Tennis", "Cricket" };
      sports.Concatenate(",").Print();

Here's code to implement "Concatenate()".

      public static string Concatenate<T>(this IEnumerable<T> items, string separator)
      {
          StringBuilder buffer = new StringBuilder();
      
          int totalItems = items.Count();
          int counter = 0;
      
          foreach (var item in items)
          {
              buffer.Append(item);
              counter++;
      
              if (counter < totalItems)
                  buffer.Append(separator);
          }
      
          return buffer.ToString();
      }

 

Coming Next

Implementing Ruby Blocks in C# (well almost).

Posted Saturday, August 4, 2007 3:34 PM by Alex Hoffman | 4 comment(s)

Filed under: , ,

More Posts