Category Archives: LINQ

Expression Tree Visualizer

Some of you may remember a rather handy ExpressionTree debugger visualizer that allowed the visualization of expressions. Basically it was extremely handy and a great way of getting to know the Expression API a bit better.

Unfortunately this was a VS2008 sample, and it does not seem to come with VS2010.

I had not been missing it as I have not been doing much with Expressions, that is until the other day, and I really started to miss it. So I set about trying to get it to work.

Here are the steps you will need to follow to get it to work

  1. Downloaded VS2008 samples from link above : http://code.msdn.microsoft.com/Visual-Studio-2008-C-d295cdba
  2. Open contained Expression Debugger Visualse project in VS2010
  3. Change the projects to target .NET4.0
  4. Change the references to point to this location for the DebuggerVisualizers.dll : C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\ReferenceAssemblies\v2.0\Microsoft.VisualStudio.DebuggerVisualizers.dll
  5. Add a DebuggerVisualizer assembly targeting attribute definition for each and ever subclass (and including) Expression
  6. Built the projects, checked that I can actually visualize an expression tree. All works fine in modified standalone project from samples
  7. Copied the ExpressionTreeVisualizer.dll to the following locations

    …\Documents\Visual Studio 2010\Visualizers …\Program Files\Microsoft Visual Studio 10.0\Common7\Packages\Debugger\Visualizers

Just in case you are curious about what I mean in  by Step 5 above, this is what I had to do

 [assembly: DebuggerVisualizer(typeof(ExpressionTreeVisualizerForVisualStudio2010), typeof(ExpressionTreeVisualizerObjectSource),      Target = typeof(Expression), Description = "Expression Tree Visualizer")] [assembly: DebuggerVisualizer(typeof(ExpressionTreeVisualizerForVisualStudio2010), typeof(ExpressionTreeVisualizerObjectSource),      Target = typeof(BinaryExpression), Description = "Expression Tree Visualizer")] [assembly: DebuggerVisualizer(typeof(ExpressionTreeVisualizerForVisualStudio2010), typeof(ExpressionTreeVisualizerObjectSource),      Target = typeof(BlockExpression), Description = "Expression Tree Visualizer")] [assembly: DebuggerVisualizer(typeof(ExpressionTreeVisualizerForVisualStudio2010), typeof(ExpressionTreeVisualizerObjectSource),      Target = typeof(ConditionalExpression), Description = "Expression Tree Visualizer")] [assembly: DebuggerVisualizer(typeof(ExpressionTreeVisualizerForVisualStudio2010), typeof(ExpressionTreeVisualizerObjectSource),      Target = typeof(ConstantExpression), Description = "Expression Tree Visualizer")] [assembly: DebuggerVisualizer(typeof(ExpressionTreeVisualizerForVisualStudio2010), typeof(ExpressionTreeVisualizerObjectSource),      Target = typeof(DebugInfoExpression), Description = "Expression Tree Visualizer")] [assembly: DebuggerVisualizer(typeof(ExpressionTreeVisualizerForVisualStudio2010), typeof(ExpressionTreeVisualizerObjectSource),      Target = typeof(DefaultExpression), Description = "Expression Tree Visualizer")] [assembly: DebuggerVisualizer(typeof(ExpressionTreeVisualizerForVisualStudio2010), typeof(ExpressionTreeVisualizerObjectSource),      Target = typeof(DynamicExpression), Description = "Expression Tree Visualizer")] [assembly: DebuggerVisualizer(typeof(ExpressionTreeVisualizerForVisualStudio2010), typeof(ExpressionTreeVisualizerObjectSource),      Target = typeof(GotoExpression), Description = "Expression Tree Visualizer")] [assembly: DebuggerVisualizer(typeof(ExpressionTreeVisualizerForVisualStudio2010), typeof(ExpressionTreeVisualizerObjectSource),      Target = typeof(IndexExpression), Description = "Expression Tree Visualizer")] [assembly: DebuggerVisualizer(typeof(ExpressionTreeVisualizerForVisualStudio2010), typeof(ExpressionTreeVisualizerObjectSource),      Target = typeof(InvocationExpression), Description = "Expression Tree Visualizer")] [assembly: DebuggerVisualizer(typeof(ExpressionTreeVisualizerForVisualStudio2010), typeof(ExpressionTreeVisualizerObjectSource),      Target = typeof(LabelExpression), Description = "Expression Tree Visualizer")] [assembly: DebuggerVisualizer(typeof(ExpressionTreeVisualizerForVisualStudio2010), typeof(ExpressionTreeVisualizerObjectSource),      Target = typeof(LambdaExpression), Description = "Expression Tree Visualizer")] [assembly: DebuggerVisualizer(typeof(ExpressionTreeVisualizerForVisualStudio2010), typeof(ExpressionTreeVisualizerObjectSource),      Target = typeof(ListInitExpression), Description = "Expression Tree Visualizer")] [assembly: DebuggerVisualizer(typeof(ExpressionTreeVisualizerForVisualStudio2010), typeof(ExpressionTreeVisualizerObjectSource),      Target = typeof(LoopExpression), Description = "Expression Tree Visualizer")] [assembly: DebuggerVisualizer(typeof(ExpressionTreeVisualizerForVisualStudio2010), typeof(ExpressionTreeVisualizerObjectSource),      Target = typeof(MemberExpression), Description = "Expression Tree Visualizer")] [assembly: DebuggerVisualizer(typeof(ExpressionTreeVisualizerForVisualStudio2010), typeof(ExpressionTreeVisualizerObjectSource),      Target = typeof(MemberInitExpression), Description = "Expression Tree Visualizer")] [assembly: DebuggerVisualizer(typeof(ExpressionTreeVisualizerForVisualStudio2010), typeof(ExpressionTreeVisualizerObjectSource),      Target = typeof(MethodCallExpression), Description = "Expression Tree Visualizer")] [assembly: DebuggerVisualizer(typeof(ExpressionTreeVisualizerForVisualStudio2010), typeof(ExpressionTreeVisualizerObjectSource),      Target = typeof(NewArrayExpression), Description = "Expression Tree Visualizer")] [assembly: DebuggerVisualizer(typeof(ExpressionTreeVisualizerForVisualStudio2010), typeof(ExpressionTreeVisualizerObjectSource),      Target = typeof(NewExpression), Description = "Expression Tree Visualizer")] [assembly: DebuggerVisualizer(typeof(ExpressionTreeVisualizerForVisualStudio2010), typeof(ExpressionTreeVisualizerObjectSource),      Target = typeof(ParameterExpression), Description = "Expression Tree Visualizer")] [assembly: DebuggerVisualizer(typeof(ExpressionTreeVisualizerForVisualStudio2010), typeof(ExpressionTreeVisualizerObjectSource),      Target = typeof(RuntimeVariablesExpression), Description = "Expression Tree Visualizer")] [assembly: DebuggerVisualizer(typeof(ExpressionTreeVisualizerForVisualStudio2010), typeof(ExpressionTreeVisualizerObjectSource),      Target = typeof(SwitchExpression), Description = "Expression Tree Visualizer")] [assembly: DebuggerVisualizer(typeof(ExpressionTreeVisualizerForVisualStudio2010), typeof(ExpressionTreeVisualizerObjectSource),      Target = typeof(TryExpression), Description = "Expression Tree Visualizer")] [assembly: DebuggerVisualizer(typeof(ExpressionTreeVisualizerForVisualStudio2010), typeof(ExpressionTreeVisualizerObjectSource),      Target = typeof(TypeBinaryExpression), Description = "Expression Tree Visualizer")] [assembly: DebuggerVisualizer(typeof(ExpressionTreeVisualizerForVisualStudio2010), typeof(ExpressionTreeVisualizerObjectSource),      Target = typeof(UnaryExpression), Description = "Expression Tree Visualizer")] 

Worked a treat and for those of you that are simply to lazy to do this work, here is zip file containing a valid VS2010 copy of a C# project that will build this Expression Debugger Visualizer for you:

http://dl.dropbox.com/u/2600965/ExpressionTreeVisualizer.zip

Advertisements

Restful WCF / EF POCO / UnitOfWork / Repository / MEF article

Numerous people have asked me to create a LOB (line of business) app that showed how I would typically structure my layers between a front end and a database (this was mainly asked for by users of my Cinch MVVM framework)

Whilst I have limited time, I am working on a rather large open source project where I kind of do a lot of this already, and I wanted to write some of that up, so I thought I could take some time out to create a rather dumbed down article which shows some of the stuff I do in my larger OSS project.

As such I published a new article which uses the following elements:

  • Inversion of control (I am using the new MEF drop)
  • Log4Net
  • Unit Of Work pattern
  • Repository pattern
  • Restful WCF using the new WCF WebApis

I have provided a simple console app demo client, for the moment. I plan on coming back and making a better front end when I have more time.

If this is of interest to you, you should pop over and read the full article over at this link : http://www.codeproject.com/KB/miscctrl/EntArch1.aspx

LINQ : 2 nice things I just found

I was at work today and had to deal with obtaining the values from some anonomous types that I was using in some WPF databinding, and although I knew I could do it with reflection, I thought someone else may have already done something, and low and behold I found something pretty cool. I found this chap that wrote a nice wrapper around an anonomous type that lets you access the property values using generics for the type of the property and strings for the key of the property. He also allows you to add new methods to the anonomous type using delegates/lambdas, all in all its a good effort. Have a look for yourself over at his blog

http://somewebguy.wordpress.com/2009/05/29/anonymous-types-round-two/

Oh and he also wrote a LINQ for JavsScript which looks very nice especially if you are trying to parse large JSON result sets. You can read more about this over at this post

http://hugoware.net/

WPF : Dynamic Search Driven List Results (Now uses AppDomain)

A couple of posts ago I showed you all how to use CodeDom/CompilerServices and LINQ to create a dynamically created dll. A few people stated that this should have been in a new AppDomain (and it was already this way at work), so I have updated the example post to show you how to create a dynamic assembly in a new AppDomain. Have a look at the original post here : http://sachabarber.net/?p=496

WPF : Dynamic Search Driven List Results

At work at the moment I am working on a way way cool customisable search that basically allows user to pick source entities and related entities and then pick what fields they would like to show, this is similar to Microsoft’s CRM Dynamics product, which allows very very sophisticated searches to be produces, by the use of a nice search UI.

Here is what CRM looks like. The search we actually built at work is even better than this, but for NDA reasons I can not show.

image

From our search we create a strongly typed Query object, which is sent across a WCF service boundary and when received at the other end, in converted to dynamic SQL, and is the  run against a SQL database. Yes that right we created our own LINQ effectively. Its call GNRSQL.

Anyway as a side effect from being able to search for anything from anywhere, we also needed the ability for our search results grid to dynamically adjust to any results set. To compound this our results objects are hierarchical in nature, and we are using the Infragistics XamDataGrid, which wants to show things in a hierarchical manner. Which is not what we wanted, so we needed to flatten the results from a hierarchy to a flat structure.

Your 1st thought might be, oh just send a DataTable across the WCF boundary, this is not a good idea, the serialization of DataTable(s) and WCF is very strange, and also incredibly heavy. Basically the namespaces get messed up and so do some of the internal field names, and my god the serialization is so far from pretty.

So we had to try some other things.

My next idea was to use IEnumerable and use LINQ to pluck out only those properties that we wanted to show based on the actually results obtained. Our results contained metadata that we could use to construct a LINQ query which would return a flattened IEnumerable of anonymous types, that had only the properties we wanted. Choosing of properties was driven by examining the actual results metadata. And all this has to happen at runtime. Doing this at design time is dead simple we can just do something like (assuming we have a list of results already)

var newFlattenedResults = (from x in results  select new { ID = x.IDField, DateOfOrder=x.OrderDate });

But how could you create something that could be used in this manner, and tailored to suit the properties returned by the search, but done at runtime. The rest of this post will show you how.

Dynamic Assemblies

.NET comes equipped with the ability to produce dynamic assemblies on the fly at runtime. So lets start there and have a look at a helper class for making this process easy.

   1:  using System.Reflection;
   2:  using System.CodeDom.Compiler;
   3:  using Microsoft.CSharp;
   4:  
   5:  using System;
   6:  using System.Collections.Generic;
   7:  using System.Text;
   8:  
   9:  namespace Dyno
  10:  {
  11:      /// <summary>
  12:      /// Utlilty class. Compliles and runs assemblies 
  13:      /// on the fly, with the option to invoke a method 
  14:      /// and return the results from the chosen
  15:      /// method
  16:      /// </summary>
  17:      public class DynamicCompiler
  18:      {
  19:          #region Public Methods
  20:          /// <summary>
  21:          /// Compiles the code and either returns the compiled code as a Type
  22:          /// or creates compiled code as a Type, and invokes the created Types
  23:          /// method. Where the method is picked by the user
  24:          /// </summary>
  25:          /// <typeparam name="T">Type of T to use</typeparam>
  26:          /// <param name="code">code to compile</param>
  27:          /// <param name="nameSpace">namespace to use for compiled code</param>
  28:          /// <param name="classToLoad">class name</param>
  29:          /// <param name="methodToRun">method to invoke (optional)</param>
  30:          /// <param name="ShouldImvokeMethod">true if you want to 
  31:          /// invoke the method</param>
  32:          /// <returns>Type of T to use</returns>
  33:          public T ComplileAndRun<T>(String code, String nameSpace,
  34:              String classToLoad, string methodToRun, Boolean ShouldImvokeMethod)
  35:          {
  36:              try
  37:              {
  38:                  String lcCode = code;
  39:  
  40:                  var provider = new CSharpCodeProvider(
  41:                          new Dictionary<String, String>()
  42:                              { { "CompilerVersion", "v3.5" } });
  43:  
  44:                  CompilerParameters parameters = new CompilerParameters();
  45:  
  46:                  // Start by adding any referenced assemblies
  47:                  parameters.ReferencedAssemblies.Add("System.dll");
  48:                  parameters.ReferencedAssemblies.Add(
  49:                      typeof(Demo.Data.Person).Assembly.Location);
  50:                  parameters.ReferencedAssemblies.Add(
  51:                      typeof(System.Linq.Enumerable).Assembly.Location);
  52:  
  53:  
  54:                  // Load the resulting assembly into memory
  55:                  parameters.GenerateInMemory = true;
  56:                  // Now compile the whole thing 
  57:                  //Must create a fully functional assembly as the code string
  58:                  CompilerResults compiledCode =
  59:                      provider.CompileAssemblyFromSource(parameters, lcCode);
  60:  
  61:                  if (compiledCode.Errors.HasErrors)
  62:                  {
  63:                      String errorMsg = String.Empty;
  64:                      errorMsg = compiledCode.Errors.Count.ToString() +
  65:                                 " n Dynamically generated code threw an error. n Errors:";
  66:  
  67:                      for (int x = 0; x < compiledCode.Errors.Count; x++)
  68:                      {
  69:                          errorMsg = errorMsg + "rnLine: " +
  70:                                     compiledCode.Errors[x].Line.ToString() + " - " +
  71:                                     compiledCode.Errors[x].ErrorText;
  72:                      }
  73:  
  74:                      throw new Exception(errorMsg);
  75:                  }
  76:  
  77:                  Assembly assembly = compiledCode.CompiledAssembly;
  78:  
  79:                  // Retrieve an obj ref – generic type only
  80:                  object instance = assembly.CreateInstance(
  81:                      nameSpace + "." + classToLoad);
  82:  
  83:                  //invoke the method if needs be, and get results 
  84:                  //back from method invocation
  85:                  if (ShouldImvokeMethod)
  86:                  {
  87:                      if (instance == null)
  88:                          return default(T);
  89:  
  90:                      T result = (T)instance.GetType().InvokeMember(
  91:                             methodToRun, BindingFlags.InvokeMethod,
  92:                             null, instance, new object[0]);
  93:  
  94:                      return result;
  95:                  }
  96:                  else
  97:                  {
  98:                      return (T)instance;
  99:                  }
 100:              }
 101:              catch (Exception ex)
 102:              {
 103:                  Console.WriteLine(String.Format(
 104:                      "An exception occurred {0}", ex.Message));
 105:                  return default(T);
 106:              }
 107:          }
 108:          #endregion
 109:      }
 110:  }

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, “Courier New”, courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }So using this helper class we can construct an in memory assembly and call a method within an object within it, or simply return the newly created object within the dynamic assembly.

So lets continue our journey, and look at a small XAML app, where there is a ListView that starts with the following columns

image

Where the XAML for this screen looks like this

   1:  <Window x:Class="DynamicLINQ.Window1"
   2:      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   3:      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:          WindowStartupLocation="CenterScreen"
   5:      Title="Window1" Height="300" Width="700">
   6:      <DockPanel LastChildFill="True">
   7:          <StackPanel DockPanel.Dock="Top" Orientation="Horizontal"
   8:                      HorizontalAlignment="Stretch" Background="CornflowerBlue">
   9:              <Button x:Name="ShowAll" Content="Show All" Margin="5"
  10:                      Click="ShowAll_Click"/>
  11:              <Button x:Name="ShowSome" Content="Show Some Columns" Margin="5"
  12:                      Click="ShowSome_Click"/>
  13:          </StackPanel>
  14:  
  15:  
  16:          <ListView x:Name="lvItems" >
  17:              <ListView.View>
  18:                  <GridView>
  19:                      <GridViewColumn Header="Age"
  20:                                      DisplayMemberBinding="{Binding Age}" />
  21:                      <GridViewColumn Header="FirstName"
  22:                                      DisplayMemberBinding="{Binding FirstName}" />
  23:                      <GridViewColumn Header="MiddleName"
  24:                                      DisplayMemberBinding="{Binding MiddleName}" />
  25:                      <GridViewColumn Header="LastName"
  26:                                      DisplayMemberBinding="{Binding LastName}" />
  27:                      <GridViewColumn Header="LastName"
  28:                                      DisplayMemberBinding="{Binding LastName}" />
  29:                      <GridViewColumn Header="ID"
  30:                                      DisplayMemberBinding="{Binding ID}" Width="230" />
  31:                      <GridViewColumn Header="DOB"
  32:                                      DisplayMemberBinding="{Binding Dob}" Width="130" />
  33:                  </GridView>
  34:              </ListView.View>
  35:          </ListView>
  36:  
  37:  
  38:      </DockPanel>
  39:  </Window>

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, “Courier New”, courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }You can see that the initial columns for the displayed results are static at this point, and are showing the results of being bound to a List<Person> objects, where a Person looks like this

   1:  using System;
   2:  using System.Collections.Generic;
   3:  using System.Linq;
   4:  using System.Text;
   5:  using System.ComponentModel;
   6:  
   7:  namespace Demo.Data
   8:  {
   9:      public class Person : INotifyPropertyChanged
  10:      {
  11:          #region Data
  12:          public Int32 age;
  13:          public String firstName;
  14:          public String middleName;
  15:          public String lastName;
  16:          public AdditionalData personData;
  17:          #endregion
  18:  
  19:          #region Public Properties
  20:          public Int32 Age
  21:          {
  22:              get { return age; }
  23:              set
  24:              {
  25:                  age = value;
  26:                  NotifyPropertyChanged("Age");
  27:              }
  28:          }
  29:  
  30:          public String FirstName
  31:          {
  32:              get { return firstName; }
  33:              set
  34:              {
  35:                  firstName = value;
  36:                  NotifyPropertyChanged("FirstName");
  37:              }
  38:          }
  39:  
  40:          public String MiddleName
  41:          {
  42:              get { return middleName; }
  43:              set
  44:              {
  45:                  middleName = value;
  46:                  NotifyPropertyChanged("MiddleName");
  47:              }
  48:          }
  49:  
  50:          public String LastName
  51:          {
  52:              get { return lastName; }
  53:              set
  54:              {
  55:                  lastName = value;
  56:                  NotifyPropertyChanged("LastName");
  57:              }
  58:          }
  59:  
  60:          public AdditionalData PersonData
  61:          {
  62:              get { return personData; }
  63:              set
  64:              {
  65:                  personData = value;
  66:                  NotifyPropertyChanged("PersonData");
  67:              }
  68:          }
  69:          #endregion
  70:  
  71:          #region INotifyPropertyChanged region
  72:          public event PropertyChangedEventHandler PropertyChanged;
  73:  
  74:          private void NotifyPropertyChanged(String info)
  75:          {
  76:              if (PropertyChanged != null)
  77:              {
  78:                  PropertyChanged(this, new PropertyChangedEventArgs(info));
  79:              }
  80:          }
  81:          #endregion
  82:      }
  83:  
  84:      public class AdditionalData : INotifyPropertyChanged
  85:      {
  86:          #region Data
  87:          private Guid id;
  88:          private DateTime dob;
  89:          #endregion
  90:  
  91:          #region Public Properties
  92:          public Guid ID
  93:          {
  94:              get { return id; }
  95:              set
  96:              {
  97:                  id = value;
  98:                  NotifyPropertyChanged("Id");
  99:              }
 100:          }
 101:  
 102:          public DateTime Dob
 103:          {
 104:              get { return dob; }
 105:              set
 106:              {
 107:                  dob = value;
 108:                  NotifyPropertyChanged("Dob");
 109:              }
 110:          }
 111:          #endregion
 112:  
 113:          #region INotifyPropertyChanged region
 114:          public event PropertyChangedEventHandler PropertyChanged;
 115:  
 116:          private void NotifyPropertyChanged(String info)
 117:          {
 118:              if (PropertyChanged != null)
 119:              {
 120:                  PropertyChanged(this, new PropertyChangedEventArgs(info));
 121:              }
 122:          }
 123:          #endregion
 124:      }
 125:  
 126:  }

So now let us see what would happen if we simulated some other search results coming back, from somewhere else, that should alter what is shown in the search results ListView.


   1:  private void ShowSome_Click(object sender, RoutedEventArgs e)
   2:  {
   3:      DataLoader dl = new DataLoader();
   4:  
   5:      //show some columns from Dynamically compiled LINQ
   6:      //query
   7:      IEnumerable results =
   8:          dl.ObtainFlattenedResults(lvItems,
   9:              people, WritePropertyType.Some);
  10:  
  11:  
  12:      lvItems.ItemsSource = results;
  13:  
  14:  }

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, “Courier New”, courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }


.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, “Courier New”, courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }


.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, “Courier New”, courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }Where people is simply a list of Person objects set up with some Person objects in it (obviously I am faking the search results part, for the sake of this article, the Person objects, would actually be some search results or something coming from the results of a search, but for this example it doesn’t matter, as I am just trying to show you how to dynamically work with LINQ at runtime)

   1:  private List<Person> people = new List<Person>();

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, “Courier New”, courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, “Courier New”, courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }You can see from the above code that we use a method called ObtainFlattenedResults() which is available in the following helper class

   1:  using System;
   2:  using System.Collections;
   3:  using System.Collections.Generic;
   4:  using System.Linq;
   5:  using System.Reflection;
   6:  using System.Text;
   7:  
   8:  using Demo.Data;
   9:  using System.Windows.Controls;
  10:  using System.Windows.Data;
  11:  
  12:  
  13:  namespace Dyno
  14:  {
  15:  
  16:      public enum WritePropertyType { All = 1, Some };
  17:  
  18:      public class EnumerableResultsCreator
  19:      {
  20:          #region Data
  21:          private readonly String generatedNamespace = "DynamicLINQ";
  22:          private readonly String generatedClassName = "ResultsWriter";
  23:          private readonly String generatedMethod = "GetResults";
  24:          private List<Person> originalResults = null;
  25:          private WritePropertyType currentPropertyType =
  26:              WritePropertyType.All;
  27:          #endregion
  28:  
  29:          #region Ctor
  30:          public EnumerableResultsCreator()
  31:          {
  32:  
  33:          }
  34:          #endregion
  35:  
  36:          #region Private Methods
  37:  
  38:          /// <summary>
  39:          /// Writes out code for class to dynamically compile
  40:          /// </summary>
  41:          private String WriteDynamicClass(WritePropertyType currentPropertyType)
  42:          {
  43:              StringBuilder code = new StringBuilder();
  44:              code.AppendLine(" using System; ");
  45:              code.AppendLine(" using System.Collections.Generic;");
  46:              code.AppendLine(" using System.Collections.ObjectModel;");
  47:              code.AppendLine(" using System.Linq;");
  48:              code.AppendLine(" using System.Text;");
  49:              //Where the DataLayer objects live
  50:              code.AppendLine(" using Demo.Data; ");
  51:              code.AppendFormat(" namespace {0}", generatedNamespace);
  52:              code.AppendLine();
  53:              code.AppendLine(" {");
  54:              code.AppendFormat(" public class {0}", generatedClassName);
  55:              code.AppendLine();
  56:              code.AppendLine(" {");
  57:              code.AppendFormat("{0}",
  58:                  this.WriteCodeProperties(currentPropertyType));
  59:              code.AppendLine();
  60:              code.Append(" }");
  61:              code.AppendLine();
  62:              code.Append(" }");
  63:              code.AppendLine();
  64:              return code.ToString();
  65:          }
  66:  
  67:  
  68:          /// <summary>
  69:          /// Either writes a LINQ query string that returns an anomomous
  70:          /// set of object with ALL properties, or just some of the properties
  71:          /// </summary>
  72:          private String WriteCodeProperties(WritePropertyType currentPropertyType)
  73:          {
  74:              StringBuilder builder = new StringBuilder();
  75:              builder.AppendFormat(
  76:                  "n public Object {0}(List<Person> results)",
  77:                      generatedMethod);
  78:              builder.AppendLine("{");
  79:  
  80:  
  81:              switch (currentPropertyType)
  82:              {
  83:                  case WritePropertyType.All:
  84:                      //OK this is a static query that could have been done in  standard LINQ
  85:                      //but this techniqe can be used to create dyanamically created
  86:                      //LINQ queries at runtime
  87:                      builder.AppendLine("var x =(from r in results select new { ");
  88:                      builder.AppendLine("         Age = r.Age,FirstName = r.FirstName,");
  89:                      builder.AppendLine("         MiddleName=r.MiddleName, LastName = r.LastName,");
  90:                      builder.AppendLine("         ID = r.PersonData.ID, Dob = r.PersonData.Dob });");
  91:                      builder.AppendLine("return x;");
  92:                      builder.AppendLine("}");
  93:                      break;
  94:                  case WritePropertyType.Some:
  95:                      //OK this is a static query that could have been done in  standard LINQ
  96:                      //but this techniqe can be used to create dyanamically created
  97:                      //LINQ queries at runtime
  98:                      builder.AppendLine("var x =(from r in results select new { ");
  99:                      builder.AppendLine("         Age = r.Age,FirstName = r.FirstName,");
 100:                      builder.AppendLine("         LastName = r.LastName});");
 101:                      builder.AppendLine("return x;");
 102:                      builder.AppendLine("}");
 103:                      break;
 104:              }
 105:  
 106:  
 107:              return builder.ToString();
 108:  
 109:          }
 110:  
 111:          /// <summary>
 112:          /// Creates the new columns for the Dynamically retrieved
 113:          /// results 
 114:          /// </summary>
 115:          private void CreateListViewColumns(IEnumerable result, ListView lv)
 116:          {
 117:              GridView gv = new GridView();
 118:  
 119:              IEnumerator e = result.GetEnumerator();
 120:              while (e.MoveNext())
 121:              {
 122:                  Type t = e.Current.GetType();
 123:                  PropertyInfo[] infos = t.GetProperties();
 124:  
 125:                  foreach (var item in infos)
 126:                  {
 127:                      GridViewColumn column = new GridViewColumn();
 128:                      column.Header = item.Name;
 129:                      Binding binding = new Binding(item.Name);
 130:  
 131:                      column.DisplayMemberBinding = binding;
 132:                      gv.Columns.Add(column);
 133:                  }
 134:                  break;
 135:              }
 136:  
 137:              lv.View = gv;
 138:          }
 139:  
 140:  
 141:          #endregion
 142:  
 143:          #region Public Method
 144:          /// <summary>
 145:          /// Create the dynamic Type invoke its method
 146:          /// and get the results
 147:          /// </summary>
 148:          public IEnumerable ObtainFlattenedResults(
 149:              ListView lv,
 150:              List<Person> originalResults,
 151:              WritePropertyType currentPropertyType)
 152:          {
 153:              if (originalResults.Count == 0)
 154:                  return null;
 155:  
 156:              this.originalResults = originalResults;
 157:  
 158:              //Create the DynamicCompiler
 159:              DynamicCompiler compiler = new DynamicCompiler();
 160:  
 161:              //Get the newly compiled object
 162:              Object dynaClass = compiler.ComplileAndRun<Object>(
 163:                  this.WriteDynamicClass(currentPropertyType),
 164:                  generatedNamespace, generatedClassName, "", false);
 165:  
 166:              //invoke its method to get the result
 167:              IEnumerable result =
 168:                  (IEnumerable)dynaClass.GetType().InvokeMember(
 169:                          generatedMethod, BindingFlags.InvokeMethod,
 170:                          null, dynaClass, new object[1]
 171:                              { this.originalResults });
 172:  
 173:              //create new ListView columns
 174:              CreateListViewColumns(result, lv);
 175:  
 176:  
 177:              return result;
 178:  
 179:          }
 180:          #endregion
 181:  
 182:      }
 183:  }

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, “Courier New”, courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }So what this class does, is construct a new code file, that is compiled using the DynamicCompiler helper class that I showed you earlier. What we then do is get an actual instance of an object back from the dynamic compilation process, which we can then use to invoke a method on.

Here is what the compiled code will look like

   1:  using System;
   2:  using System.Collections.Generic;
   3:  using System.Collections.ObjectModel;
   4:  using System.Linq;
   5:  using System.Text;
   6:  using Demo.Data;
   7:  namespace DynoGen
   8:  {
   9:      public class ResultsWriter
  10:      {
  11:  
  12:          public Object GetResults(List<Person> results)
  13:          {
  14:              var x = (from r in results
  15:                       select new
  16:                       {
  17:                           Age = r.Age,
  18:                           FirstName = r.FirstName,
  19:                           LastName = r.LastName
  20:                       });
  21:              return x;
  22:          }
  23:  
  24:      }
  25:  }

But Beware

As we are effectivly creating a new dynamically created Dll in memory in our current AppDomain this could lead to the current AppDomain getting bigger and bigger. So it is a good idea to do all this in a new AppDomain, but how do we do that?

Well that is actually pretty simple, we can do this

   1:  using System;
   2:  using System.Collections.Generic;
   3:  using System.Linq;
   4:  using System.Text;
   5:  
   6:  using Demo.Data;
   7:  using System.Windows.Controls;
   8:  using System.Collections;
   9:  using System.IO;
  10:  using System.Runtime.Remoting;
  11:  using System.Reflection;
  12:  
  13:  namespace DynamicLINQ
  14:  {
  15:      /// <summary>
  16:      /// Obtains dynamic results using a seperate AppDomain that is 
  17:      /// unloaded when the work is finished with the Dyanamic Assembly
  18:      /// </summary>
  19:      public class DataLoader
  20:      {
  21:          public IEnumerable ObtainFlattenedResults(
  22:              ListView lv,
  23:              List<Person> originalResults,
  24:              WritePropertyType currentPropertyType)
  25:          {
  26:  
  27:              //Create new app domain            
  28:              AppDomain domain = AppDomain.CreateDomain("ResultsDomain");
  29:              IEnumerable results = null;
  30:              Object instance = null;
  31:  
  32:  
  33:              try
  34:              {
  35:  
  36:                  //load search assembly
  37:                  domain.Load(File.ReadAllBytes(String.Format(@"{0}{1}",
  38:                      Environment.CurrentDirectory,
  39:                       "Dyno.dll")));
  40:  
  41:                  //Get the EnumerableResultsCreator instance
  42:                  ObjectHandle instanceHandle = domain.CreateInstance("Dyno",
  43:                                      String.Format("{0}.{1}"
  44:                                      , "Dyno"
  45:                                      , "EnumerableResultsCreator"));
  46:  
  47:                  if (instanceHandle != null)
  48:                      instance = instanceHandle.Unwrap();
  49:  
  50:                  //call method to get IEnumerable results
  51:                  if (instance != null)
  52:                      results = instance.GetType().InvokeMember
  53:                          ("ObtainFlattenedResults",
  54:                                  BindingFlags.InvokeMethod,
  55:                                  null,
  56:                                  instance,
  57:                                  new object[3] {
  58:                                      lv
  59:                                      , originalResults
  60:                                      , currentPropertyType }
  61:                          ) as IEnumerable;
  62:              }
  63:              catch (Exception e)
  64:              {
  65:                  Console.WriteLine("Problem constructing the " +
  66:                      "EnumerableResultsCreator instance");
  67:              }
  68:              finally
  69:              {
  70:                  AppDomain.Unload(domain);
  71:              }
  72:              return results;
  73:          }
  74:      }
  75:  }

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, “Courier New”, courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }This takes care of managing a new AppDomain and gets the results from the dynamic assembly, and then unloads the new AppDomain. This ensures the primary applications AppDomain doesn’t get any unwanted code in it.

So you can see that we are creating an actual class that accepts a List<Person> (the fake search results) and uses some LINQ to grab out ONLY the properties we want to use all rolled up in an anonymous which is selected as a single flattened search result for the search results grid. Remember this is all happening at RUNTIME, so we can do what we like, we can manipulate the results as much as we like, as the code we compile is just a String.

The other thing that happens is that the WPF ListView columns are altered to only show the necessary  columns based on the newly flattened search results.

Some grid works nicer with anonymous types, though so far the WPF Toolkit DataGrid failed, and so does the ListView, that is why we need to do the trick with re-creating the columns based on the new results. At work we are using the Infragistics xamDataGrid, and it works straight out of the can with anonymous types, we do not have to mess about with columns at all, it just knows what to do.

Here is the results

Showing ALL Columns Of Results

image

Which is done using the following logic

   1:                  case WritePropertyType.All:
   2:                      //OK this is a static query that could have been done in  standard LINQ
   3:                      //but this techniqe can be used to create dyanamically created
   4:                      //LINQ queries at runtime
   5:                      builder.AppendLine("var x =(from r in results select new { ");
   6:                      builder.AppendLine("         Age = r.Age,FirstName = r.FirstName,");
   7:                      builder.AppendLine("         MiddleName=r.MiddleName, LastName = r.LastName,");
   8:                      builder.AppendLine("         ID = r.PersonData.ID, Dob = r.PersonData.Dob });");
   9:                      builder.AppendLine("return x;");
  10:                      builder.AppendLine("}");

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, “Courier New”, courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }Showing Selected Columns Of Results (see we only get some of the columns)

image

Which is done using the following logic

   1:                  case WritePropertyType.Some:
   2:                      //OK this is a static query that could have been done in  standard LINQ
   3:                      //but this techniqe can be used to create dyanamically created
   4:                      //LINQ queries at runtime
   5:                      builder.AppendLine("var x =(from r in results select new { ");
   6:                      builder.AppendLine("         Age = r.Age,FirstName = r.FirstName,");
   7:                      builder.AppendLine("         LastName = r.LastName});");
   8:                      builder.AppendLine("return x;");
   9:                      builder.AppendLine("}");
  10:                      break;

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, “Courier New”, courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }Here is a small demo project

dynamiclinq1.zip

Now I know this is a very specific business case, and not many people will do this exactly, but it did lead to some very interesting code, that I thought I could share with you, it does show you how to work with dynamically compiled assemblies.

IMPORTANT NOTE

For this example I could have used the Dynamic LINQ library Dll, which is discussed over at Scott Guthrie’s blog.

http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

However this technique is a powerful one, and could be used for a great many use cases, where you need to run some dynamic code that you only know about at runtime. It just happens to be I chose to use LINQ as the demonstration tool, at work we actually use the Dynamic LINQ library Dll, but the rest is the same.

Who Wants Me To Write A Book

Recently someone left me the following message on my new article (http://www.codeproject.com/KB/smart/GeoPlaces.aspx)

Hi Sacha,
I’m sure this has been said before but you really should write a book imho.
I’d buy it …
I’m not going to vote a 5 because I’d rather vote with my cash frankly!!
Oh, alright then … Wink
<stick>
Gold Star
</stick>
Seriously, write a book, but don’t do the predictable thing of picking a single technology. I like your whole approach and passion. This article would make a killer chapter in said book for instance …
Best Regards,

Jammer : 05/04/2009

Now this is not the 1st time someone has suggested that I write a book, I was just wondering how many people would actually like me to write a book. If you would could you leave a comment here, so that I can tell who would buy the book, and how many folk think it would be a good idea.

The sort of thing that I would try and cover is what I normally cover, which would be how to work with a mixture of technologies all used together, So this may include WCF/WPF/WF/LINQ/Custom controls/ASP .NET Silverlight all working together. Typically this would be to solve some problem that I make up, where the problem show cases how to use the technology really.

Let me know thanks

PS : I am running out of time to say thanks to all of you that have encouraged me to do this. I am going to look into it. I just wanted to say a big thanks to you all.

Double Whammy Goodness

I just got an email from Chris Maunder today to tell me that my Sonic article (http://www.codeproject.com/KB/smart/Sonic.aspx) has won the 2 following awards, that’s 2 awards

  • Best C# article of February 2009
  • Best overall article of February 2009

Excellent today winning articles, tomorrow the world. Muah Ha Ha

 

Too be honest I was very pleased with Sonic, so I am happy it has done well.

A simple SGML Parser and Visitor pattern loveliness

I am in the middle of so many article ideas right now that I am finding it hard to find enough time to look at them all, and some of them are pretty big articles. So what I have to do when this happens, is break them down into smaller areas, and look and see if any of the bigger articles would become clearer if I wrote it in smaller parts.

I am currently working on one that has to do with extending LINQ and the whole System.Linq.Expressions namespace idea in general. Now I don’t want to give too much away about what I will be doing, but one of the fundamental parts of how the whole System.Linq.Expressions namespace works, is by the use of the "Visitor Pattern".

If you have not used this pattern before, it is a structural pattern that can be used keep the algorithm separate from the object structure. I have used this pattern on a few different occasions and I for one really like it, though I do feel the standard visitor pattern could be improved a little.

I have written a small article talking about the standard a possibly improved visitor pattern over at www.codeproject.com, you can use the following link to read more.

http://www.codeproject.com/KB/recipes/ReflectVisitor.aspx

Enjoy

A Journey Into Expressions

I have been a little obsessed with LINQ and Func<T,TResult> of late and finally managed to find some time to do a little bit of exploration into the System.Linq.Expressions namespace.

I have published an article over at codeproject (http://www.codeproject.com/KB/linq/Expressions.aspx) which tells you all about how to create the following

lamda expression : (x) => x.Length > 1 , entirely in code using the System.Linq.Expressions namespace.

In case you are curious this is what this expression looks like when working with the System.Linq.Expressions namespace:

 

   1:  ConstantExpression constLength = Expression.Constant(1);
   2:   
   3:  ParameterExpression stringParameter = 
   4:      Expression.Parameter(typeof(String), "s");
   5:   
   6:  MemberExpression stringMember = 
   7:      LambdaExpression.PropertyOrField(stringParameter, "Length");
   8:   
   9:   
  10:  Expression<Func<String, Boolean>> bindLambda =
  11:      Expression.Lambda<Func<String, Boolean>>
  12:      (
  13:          Expression.GreaterThan(
  14:          stringMember,
  15:          constLength),
  16:          stringParameter
  17:      );
  18:   
  19:   
  20:  foreach (String bindingString in 
  21:      bindings.Where(bindLambda.Compile()))
  22:  {
  23:     .....
  24:  }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

In the article I obvisouly talk in a lot more detail, so if you want to know more, just have a look at the full article http://www.codeproject.com/KB/linq/Expressions.aspx

Reading Feeds with XLINQ

I have done a number of projects that all parse RSS Feeds using XLINQ. Which in itself is awesome, and much easier than using old XML techniques. Where I would so something like

   1:  public static List<PhotoInfo> LoadLatestPictures()
   2:  {
   3:   try
   4:   {
   5:     var xraw = XElement.Load(MOST_RECENT);
   6:     var xroot = XElement.Parse(xraw.ToString());
   7:     var photos = (from photo in xroot.Element("photos").
   8:     Elements("photo")
   9:      select new PhotoInfo
  10:      {
  11:        ImageUrl =
  12:        string.Format(
  13:        "http://farm{0}.static.flickr.com/{1}/{2}_{3}_m.jpg",
  14:        (string)photo.Attribute("farm"),
  15:        (string)photo.Attribute("server"),
  16:        (string)photo.Attribute("id"),
  17:        (string)photo.Attribute("secret"))
  18:      }).Take(Constants.ROWS * Constants.COLUMNS);
  19:              return photos.ToList<PhotoInfo>();
  20:    }
  21:    catch (Exception e)
  22:    {
  23:      Trace.WriteLine(e.Message, "ERROR");
  24:    }
  25:    return null;
  26:  }

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, “Courier New”, courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, “Courier New”, courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }However today I found something even cooler.

Have a look at the code below.

   1:  using System.ServiceModel.Syndication;
   2:  using System.Xml;
   3:  using System.IO;
   4:  using System.Xml.Linq;
   5:  
   6:  public class DataService : IDataService
   7:  {
   8:      public SyndicationFeedFormatter GetGeoRSS()
   9:      {
  10:          var geoRss =
  11:          @"<?xml version='1.0' encoding='utf-8' ?>
  12:              <rss version='2.0'
  13:                  xmlns:geo='http://www.w3.org/2003/01/geo/wgs84_pos#'
  14:                  xmlns:georss='http://www.georss.org/georss'
  15:                  xmlns:gml='http://www.opengis.net/gml'
  16:                  xmlns:mappoint='http://virtualearth.msn.com/apis/annotate#'>
  17:                <channel>
  18:                  <title>Mount Saint Helens - Mount Margaret Trail</title>
  19:                  <link></link>
  20:                  <description>Trailheads and campsites in the Mount
  21:                  Margaret area of
  22:                  Mount Saint Helens, WA</description>
  23:                  <mappointIntlCode>cht</mappointIntlCode>
  24:                  <item>
  25:                    <title>Coldwater Lake</title>
  26:                    <description>Formed by the 1980 eruption of
  27:                      Mount St. Helens.</description>
  28:                    <georss:polygon>46.31409 -122.22616 46.31113
  29:                      -122.22968 46.31083 -122.23320 46.29802
  30:                      -122.25877 46.29245 -122.26641 46.29286 -122.26392
  31:                      46.28746 -122.26744 46.28741 -122.26006
  32:                      46.29049 -122.25955 46.29120 -122.25620
  33:                      46.28924 -122.255430 46.30271 -122.23251
  34:                      46.31284 -122.22315
  35:                      46.31409 -122.22616</georss:polygon>
  36:                    <icon>http://dev.live.com/virtualearth/sdk/
  37:                      img/hiking_icon.gif</icon>
  38:                  </item>
  39:                  <item>
  40:                    <title>Lakes Trailhead</title>
  41:                    <description>This is where we started our hike,
  42:                      just down the road from the visitor center.
  43:                      You could also start at the visitor center.
  44:                  </description>
  45:                    <geo:lat>46.2913246</geo:lat>
  46:                    <geo:long>-122.2658157</geo:long>
  47:                  </item>
  48:                </channel>
  49:              </rss>";
  50:  
  51:          var xDoc = XDocument.Parse(geoRss);
  52:          var feed = SyndicationFeed.Load(xDoc.CreateReader());
  53:  
  54:          Rss20FeedFormatter feed2 = Rss20FeedFormatter(feed);
  55:          return feed2;
  56:      }
  57:  }

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, “Courier New”, courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, “Courier New”, courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

The thing to note here is the “SyndicationFeed” and “Rss20FeedFormatter” classes. How cool is that.

So when you a  Rss20FeedFormatter object, you get properties to get straight to all the usual RSS things you would like to use, such as Feed.Items

image

This is very cool. I am constantly being surprised by just what .NET can do, it just goes to show you need to keep an eye on the namespaces. There are new ones in there all the time.

System.ServiceModel.Syndication Huh, well I’ll be.