Skip to main content
/_layouts/images/titlegraphic.gif

Peter Himschoot's Windows Foundation Trilogy

Go Search
Peter Himschoot's Windows Foundation Trilogy
U2U Website
  

Talking about .NET, Windows Presentation Foundation, Workflow Foundation and Communication Foundation

 Image Web Part

Peter at U2U booth during TechEd Eur 2006
  U2U Home
  U2U Course Calendar
Talking about .NET, Windows Presentation Foundation, Workflow Foundation and Communication Foundation
My blog has moved

A while ago we started using our new blog center (http://blogs.u2u.be), so please redirect your favourite blog reader to : http://blogs.u2u.be/Peter/ 

If you want you can now subscribe to all the U2U blog posts at http://blogs.u2u.be/all/rss

Hope to see you there. You might like to check out some of my recent posts which I didn’t post to this old blog… Sorry for that ;)

What would you like in Silverlight 4.0?

Hey, if you know about a cool features you know Silverlight couldn’t live without, go visit silverlight.uservoice.com and give it to them!

Which browser is best for your battery life? IE 8.0!

I’ve just found this little article which compares browsers for battery life, and IE 8.0 beats even firefox!

Cool Stuff on SketchFlow

Katrien De Graeve put a very nice series on SketchFlow on her blog. Even better, you can watch them in English, Dutch or French! Hey, Belgium is a multi-language country, this this proves it ! :)

Using T4 to automatically generate your entities

Today I discovered something very interesting, namely how to automatically generate my entity classes (classes that also implement the INotifyPropertyChanged and IDataErrorInfo interfaces) using T4.

T4 is a text generation language built into Visual Studio 2005 and later, normally intended for DSL code generation. But we can also use it for generating any code we would like. I for one, I would like automatic properties to automatically implement INotifyPropertyChanged if the interface is on the class, but of course, life doesn’t work that way *sigh*. The real problem is that for each property you have, part of the implementation needs to raise an event using the property name. When you change the name of the property you also have to change this string, which is error prone…

Instead we can generate code using T4, and to be honest, it isn’t that difficult to use. First of all, go to tangible to download their free T4 intelli-sense tool.

Next add to your project a new text file, naming it Entity.tt (the extension is important!). Now add this content:

<#@ template language="C#" #>
<#@ output extension="cs" #>
<#@ import namespace="System.Collections" #>
<#@ import namespace="System.Collections.Generic" #>
// ---------------------------------
// U2U Sample, use at your own risk!
//        http://www.u2u.be
// ---------------------------------

using System;
using System.ComponentModel;
using System.Collections.Generic;

namespace <#= this.Namespace #> 
{  
  public partial class <#= this.ClassName #> 
    : INotifyPropertyChanged
    , IDataErrorInfo  
  {
    #region Private fields
    <# for (int idx = 0; idx < this.properties.GetLength(0); idx++) { #>    
    private <#= this.properties[idx,0] #> _<#= this.properties[idx,1].ToLower() #>;<# }#>   
    
    #endregion
    
    #region Properties
    <# for (int idx = 0; idx < this.properties.GetLength(0); idx++) { #>    
    public <#= this.properties[idx,0] #> <#= this.properties[idx,1] #>
    {        
      get
      {            
        return _<#= this.properties[idx,1].ToLower() #>;        
      }        
      set        
      {            
        _<#= this.properties[idx,1].ToLower() #> = value;
        OnPropertyChanged("<#= this.properties[idx,1]#>");        
      }   
    }
    <#   }   #>      
    #endregion
    
    #region INotifyPropertyChanged Members   
    
    public event PropertyChangedEventHandler PropertyChanged;
    
    protected virtual void OnPropertyChanged(string propertyName)   
    {       
      if (PropertyChanged != null)           
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));   
    }   
    
    #endregion
    
    #region IDataErrorInfo Members
    
    private string _error = null;
    
    public string Error {
      get
      { 
        return _error; 
      }
      set 
      {
        _error = value;
      }
    }
    
    private Dictionary<string,string> _columnErrors =
      new Dictionary<string,string>();
      
    public string this[string columnName]
    {
      get
      {
        if( _columnErrors != null && _columnErrors.ContainsKey(columnName))
          return _columnErrors[columnName];
        else
          return null;
      }
      set
      {
        if( value != null ) // Insert error
        {
          if( _columnErrors == null )
          {
            _columnErrors = new Dictionary<string,string>();
          }
          _columnErrors[columnName] = value;
        }
        else // Clear error
        {
          _columnErrors.Remove(columnName);
          if (_columnErrors.Count == 0)
          {
            _columnErrors = null;
          }
        }
        // Notify validation that something has changed
        OnPropertyChanged( columnName );
      }
    }
    #endregion
  }
}

<#+    
  string Namespace = "Demo";    
  string ClassName = "DemoClass";    
  string[,] properties = {        
    {"int", "Property1"},        
    {"string", "Property2"}
  };               
#>

Building your project will generate a little DemoClass with these two properties. But that is of course not what you want; so add another file Category.tt:

<#    
  this.Namespace = "U2U.Samples";    
  this.ClassName = "Category";    
  this.properties = new string[,]
  {        
    {"int"   , "CategoryID"}
  , {"string", "CategoryName"}      
  , {"string", "Description"}      
  , {"byte[]", "Picture"}
  }; 
#>

<#@ include file="Entity.tt" #>

Building will now automatically generate a Category.cs file with code like this:

// ---------------------------------
// U2U Sample, use at your own risk!
//        http://www.u2u.be
// ---------------------------------

using System;
using System.ComponentModel;
using System.Collections.Generic;

namespace U2U.Samples
{
  public partial class Category
    : INotifyPropertyChanged
    , IDataErrorInfo
  {
    #region Private fields

    private int _categoryid;
    private string _categoryname;
    private string _description;
    private byte[] _picture;

    #endregion

    #region Properties

    public int CategoryID
    {
      get
      {
        return _categoryid;
      }
      set
      {
        _categoryid = value;
        OnPropertyChanged("CategoryID");
      }
    }

    public string CategoryName
    {
      get
      {
        return _categoryname;
      }
      set
      {
        _categoryname = value;
        OnPropertyChanged("CategoryName");
      }
    }

    public string Description
    {
      get
      {
        return _description;
      }
      set
      {
        _description = value;
        OnPropertyChanged("Description");
      }
    }

    public byte[] Picture
    {
      get
      {
        return _picture;
      }
      set
      {
        _picture = value;
        OnPropertyChanged("Picture");
      }
    }

    #endregion

    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName)
    {
      if (PropertyChanged != null)
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

    #endregion

    #region IDataErrorInfo Members

    private string _error = null;

    public string Error
    {
      get
      {
        return _error;
      }
      set
      {
        _error = value;
      }
    }

    private Dictionary<string, string> _columnErrors =
      new Dictionary<string, string>();

    public string this[string columnName]
    {
      get
      {
        if (_columnErrors != null && _columnErrors.ContainsKey(columnName))
          return _columnErrors[columnName];
        else
          return null;
      }
      set
      {
        if (value != null) // Insert error
        {
          if (_columnErrors == null)
          {
            _columnErrors = new Dictionary<string, string>();
          }
          _columnErrors[columnName] = value;
        }
        else // Clear error
        {
          _columnErrors.Remove(columnName);
          if (_columnErrors.Count == 0)
          {
            _columnErrors = null;
          }
        }
        // Notify validation that something has changed
        OnPropertyChanged(columnName);
      }
    }
    #endregion
  }
}

So to change/add/remove a property, we edit the Category.tt file and all the rest is done automatically.

Now for some feedback, what is your way of implementing IDataErrorInfo?
Entity Framework Tips & Tricks

If you’re into EF, I encourage you to view this webcast made by Julia Lerman, Autor of Programming Entity Framework.

No more waiting for Azure tokens

While looking into Azure today, I couldn’t resist telling you that since today, you don’t need to wait for the confirmation to get your Azure development token! Great news.

Read more about it here.

Changing the generated code namespace when adding a Service Reference

In my previous post I described how to change the default xml namespace used for serialization. But how can you change the generated namespace in your code? This is actually quite simple in Visual Studio. After adding the Service Reference, click on the Show All Files button in Solution explorer and look for the .svcmap file. In it you’ll find a <NamespaceMapping> section. Simply add the xml namespace and required Clr namespace to it:

    <NamespaceMappings>
      <NamespaceMapping TargetNamespace="http://www.u2u.be/samples/wcf/2009"
                        ClrNamespace="U2U.Samples"/>
    </NamespaceMappings>
Setting the default namespace just once for your (data) contracts in WCF

While browsing around the WCF REST starter toolkit I found this attribute:

[assembly: ContractNamespace()]

So what does it do? Well, normally if you don’t specify an explicit namespace in your datacontract, the DataContractSerializer uses its own default, namely generated from the CLR namespace. For example this datacontract:

namespace U2U.DataContracts
{
  [DataContract]
  public class Person
  {
    [DataMember]
    public string Name { get; set; }

    [DataMember]
    public Job Occupation { get; set; }
  }

  [DataContract]
  public class Job
  {
    [DataMember]
    public string Description { get; set; }
  }
}

will be serialized like this:

<Person xmlns="http://schemas.datacontract.org/2004/07/U2U.DataContracts" 
        xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <Name>Jefke</Name>
  <Occupation>
    <Description>Developer</Description>
  </Occupation>
</Person>

But if you use the ContractNamespace attribute:

[assembly: ContractNamespace("http://www.u2u.be/samples/wcf/2009", ClrNamespace = "U2U.DataContracts")]

namespace U2U.DataContracts
{
  [DataContract]
  public class Person
  { … }

  [DataContract]
  public class Job
  { … }
}

The output now looks like this:

<Person xmlns="http://www.u2u.be/samples/wcf/2009" 
        xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <Name>Jefke</Name>
  <Occupation>
    <Description>Developer</Description>
  </Occupation>
</Person>

The attribute requires two things, the first is the default namespace to use, the second is the CLR namespace of your datacontract. If you have multiple CLR namespaces for your  data contracts, you will need to repeat this attribute for each namespace. For example:

[assembly: ContractNamespace("http://www.u2u.be/samples/wcf/2009", ClrNamespace = "U2U.DataContracts")]
[assembly: ContractNamespace("http://www.u2u.be/samples/wcf/2009", ClrNamespace = "U2U.Jobs")]

namespace U2U.DataContracts
{
  [DataContract]
  public class Person
  {
    [DataMember]
    public string Name { get; set; }

    [DataMember]
    public Job Occupation { get; set; }
  }
}

namespace U2U.Jobs
{
  [DataContract]
  public class Job
  {
    [DataMember]
    public string Description { get; set; }
  }
}
will give you the same output as the previous example.
LINQ Cheat Sheet

Last week (and next week) I was teaching a lot about LINQ, but I wish I could have given everyone one of these handy cheat sheets!!! Thank you Damien!

1 - 10 Next

 Content Editor Web Part

 ‭(Hidden)‬ Admin Links