LINQ to SQL using SoC

June 23, 2010 09:55 by bryan

I have had a few people saying that LINQ to SQL is hard to use for Separation of Concerns, so I've created a small project that show how to do it.  I have used the MEF as my SoC framework.

Project is using .Net 3.5

SoCLINQ2SQL.zip (905.61 kb)

To enhance this it is worth look at Mike Hadlow post of Repository.GetById using LINQ Expression Syntax


MEF not supporting open generic types

June 23, 2010 09:32 by bryan

If you are trying to use MEF with open generic types like:

[Export(typeof(IRepository<>))]
public class itial; padding: 0px; margin: 0px; border: 0px initial initial;">Repository<T> : IRepository<al; background-color: transparent; color: black; background-position: initial initial; background-repeat: initial initial; padding: 0px; margin: 0px; border: 0px initial initial;">T>
   
where T : class
{

With an import of

[Import(typeof(IRepository<>))]
private IRepository<Contact> repository;

You'll come stuck, as the current implementation MEF does not support Open Generic Types.

For more information take a look at Glenn Block article Why doesn’t MEF support open-generics for exports? Because MEF is not type based

Also there is Open-generic support in the MEF Contrib, which can be found on codeplex.

The reasoning is this, MEF parts relate on contracts which are strings, not types. To illustrate, see the code below.

namespace Orders {

  public interface IOrderRepository {}

  [Export(typeof(IOrderRespository))]

  public class OrderRepository : IOrderRepository {

  }

}

Although I have passed typeof(IOrderRepsitory) to the export, that is just a convenience that gets converted to a contract name of "Orders.IOrderRepository". The same applies to the importer...

[Export]

public class OrderService(

  [Import]

  public IOrderRepository Repository {gets;set;} 

)

The import on IOrderRepository also gets converted to a contract name of "Orders.IOrderRepository". This way the container is able to satisfy the import as the 2 contracts match. In the same way we support closed generics, so....

public interface IRepository<T> {}

namespace Orders {

  [Export(typeof(IRepository<Order>))]

  public class OrderRepository : IRepository<Order> {

  }

}

[Export]

public class OrderService(

  [Import]

  public IRepository<Order> Repository {gets;set;} 

)

Will work because the OrderRepository is exporting the contractname "Orders.IRepository<Order>" and the OrderService is importing the same contract.

However, this is what it looks like if we try the same with open generics.

public interface IRepository<T> {}

namespace Utils {

  [Export(typeof(IRepository<>))]

  public class Repository : IRepository<T> {

  }

}

[Export]

public class OrderService(

  [Import]

  public IRepository<Order> Repository {gets;set;} 

Now the contract names will be different. The exporter will have a contract of  "Utils.IRepository<>" and the importer will have a contract of "Utils.IRepository<Order>".

It is a simple match up, that breaks down in the open-generics case. This is because fundamentally, MEF is not matching on type.

Original article form codeplex


AutoMapper

June 18, 2010 09:16 by bryan

I have just given an hour presentation on AutoMapper, and great Object to Object mapper.

Here is the source file with the samples

AutoMapper.zip (855.99 kb)


How to serialize/deserialize a nullable date

June 11, 2010 09:04 by bryan

The time will come when you are serializing and deserializing object to and from XML that you will come across nullable dates, or more correctly an attribute XML date that is nullable.  If you are like me and using the System.Xml.Serialization namespace, which make the complete process of serializing and deserializing so much easier.

Here is the issue, the code below is a nullable datetime, which is fine in .NET

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 


        private DateTime? dob;
        [XmlAttribute]
        public DateTime? DOB
        {
            get
            {
                return dob;
            }
            set
            {
                dob = value;
            }
        }

When you come the serialize/deserialize you find you get an error of:

System.InvalidOperationException: Cannot serialize member 'DOB' of type System.Nullable`1[System.DateTime]. XmlAttribute/XmlText cannot be used to encode complex types.

So to over come this you have a number of options, the one I have come up with is to pull the date in using a string and then pre-process the date and then store it in to the nullable date field, like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
 


        private DateTime? dob;
        [XmlIgnore]
        public DateTime? DOB
        {
            get
            {
                return dob;
            }
            set
            {
                dob = value;
            }
        }


        [XmlAttribute("DOB")]
        public string DoBstring
        {
            get { 
                return DOB.HasValue
                ? XmlConvert.ToString(DOB.Value, XmlDateTimeSerializationMode.Unspecified)
                : string.Empty;
            }
            set { 
                DOB = 
                !string.IsNullOrEmpty(value)
                ? XmlConvert.ToDateTime(value, XmlDateTimeSerializationMode.Unspecified)
                : (DateTime?) null;
            }
        }

You notice that the nullable Date field is not decorated with an XmlIgnore attribute, and the string is picking up the DOB attribute tag

 

 


How to use DataAnnotations Validation

May 26, 2010 11:14 by bryan

The use of DataAnnotations, has increased over the years, as many frameworks are using it more and more, (MVC, Silverlight, etc).

However if you need to perform validation within your application and it is not any known framework then can we still use DataAnnotations?

The answer is yes, I'll try and take you through how you can go about it.

First lets create a class that we are going to use:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
    public class Contact
    {


        [Required]
        [RegularExpression(@"\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*([,;]\s*\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*)*", ErrorMessage = "Invalid email address")]
        public string Email { get; set; }


        [Required]
        [StringLength(20)]
        public string FirstName { get; set; }


        [Required]
        public string LastName { get; set; }


        [Range(10,30)]
        public int Age {get;set;}


        public string City { get; set; }   


    }

All of these validations are standard and out of the box when using DataAnnotations.

Next we need to be able to hold the Error Information, so I've created a class called ErrorInfo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
    public class ErrorInfo
    {
        public ErrorInfo(string propertyName, string errorMessage, object instance)
        {
            PropertyName = propertyName;
            ErrorMessage = errorMessage;
            Instance = instance;
        }


        public string PropertyName { get; set; }
        public string ErrorMessage { get; set; }
        public object Instance { get; set; }


    }

Now the clever bit, the Validation Runner (this was kindly supplied by Steve Sanderson and his xVal)

1
2
3
4
5
6
7
8
9
10
11
12
13
 


    internal static class DataAnnotationsValidationRunner
    {
        public static IEnumerable<ErrorInfo> GetErrors(object instance)
        {
            return from prop in TypeDescriptor.GetProperties(instance).Cast<PropertyDescriptor>()
                   from attribute in prop.Attributes.OfType<ValidationAttribute>()
                   where !attribute.IsValid(prop.GetValue(instance))
                   select new ErrorInfo(prop.Name, attribute.FormatErrorMessage(string.Empty), instance);
        }
    }

So that is the hard work done, now lets check for validation:

1
     IEnumerable<ErrorInfo> errors = DataAnnotationsValidationRunner.GetErrors(contact);

How easy is that?

Okay now lets pick things up, What I would like to do next is Validate the City, to be a city in the UK, something like this would be nice:

1
2
      [City(ValidCity="Gloucester")]
      public string City { get; set; }

In order to do this you are going to have to generate your own Attribute which needs to be based on the ValidationAttribute, again this is quite simple

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
 


    public class CityAttribute : ValidationAttribute
    {
        public string ValidCity { get; set; }


        public override bool IsValid(object value)
        {
            if (value == null)
            {
                return true;
            }


            if (value.ToString() != ValidCity)
            {
                return false;
            }


            return true;
        }
    }


 

So you now can generate your own custom validation attributes with your own business rules.

DataAnnotationsValidation.zip (11.78 kb)


Casing Objects using Interfaces

March 19, 2010 16:24 by bryan

Some times you need to cast from one object to the other, and then back again, the easiest way of doing this is using Interface casting, I've generated this simple project which show how it works.

Interface Tests.zip (34.05 kb)


enums with real world names

March 4, 2010 18:54 by bryan

Enums are a wonderful addition to .Net, but won't it be nice to have a real world description that you can display to the user interface? Well you can, and here is how define an attribute (or use existing DisplayNameAttribute) and annotate your enum with names as additional meta-data:

public enum Unit
{
    [DisplayName("Hz")] Hertz,
    [DisplayName("%V")] Volt
}


How do you retrieving the XmlEnumAttribute values for an Enum

January 8, 2010 06:27 by bryan

When you are playing with Web Services you quite often find information held in an Attribute, but how do you get it out?

e.g.

public enum Classification {

        [System.Xml.Serialization.XmlEnumAttribute("Test drive demonstrator")]
        Testdrivedemonstrator,

        [System.Xml.Serialization.XmlEnumAttribute("Showroom vehicle")]
        Showroomvehicle,

 

By using reflection you can gain access to the attribute, here is how:

Type enumType = typeof(velocityUom);

foreach (FieldInfo fi in enumType.GetFields())

{

object[] attrs = fi.GetCustomAttributes(typeof(XmlEnumAttribute), false);

if (attrs.Length > 0)

{

Console.WriteLine(((XmlEnumAttribute)attrs[0]).Name);

}

}

 


Culture Codes

June 19, 2009 11:07 by bryan

 

A comprehensive list of culture codes used for localising and in conjunction with the CultureInfo class.

The CultureInfo class specifies a unique name for each culture, based on RFC 4646 (Windows Vista and later). The name is a combination of an ISO 639 two-letter lowercase culture code associated with a language and an ISO 3166 two-letter uppercase subculture code associated with a country or region.

CodeLanguage - Country/RegionCodeLanguage - Country/Region
af Afrikaans hu-HU Hungarian - Hungary
af-ZA Afrikaans - South Africa is Icelandic
sq Albanian

 

is-IS Icelandic - Iceland
sq-AL Albanian - Albania id

 

Indonesian
ar Arabic id-ID Indonesian - Indonesia

 

ar-DZ Arabic - Algeria it Italian
ar-BH Arabic - Bahrain it-IT Italian - Italy
ar-EG Arabic - Egypt it-CH Italian - Switzerland
ar-IQ Arabic - Iraq ja Japanese
ar-JO Arabic - Jordan ja-JP Japanese - Japan
ar-KW Arabic - Kuwait kn Kannada
ar-LB Arabic - Lebanon kn-IN Kannada - India
ar-LY

 

Arabic - Libya kk Kazakh
ar-MA Arabic - Morocco

 

kk-KZ Kazakh - Kazakhstan
ar-OM Arabic - Oman kok

 

Konkani
ar-QA Arabic - Qatar kok-IN Konkani - India

 

ar-SA Arabic - Saudi Arabia ko Korean
ar-SY Arabic - Syria ko-KR Korean - Korea
ar-TN Arabic - Tunisia ky Kyrgyz
ar-AE Arabic - United Arab Emirates ky-KG Kyrgyz - Kyrgyzstan
ar-YE Arabic - Yemen lv Latvian
hy Armenian lv-LV Latvian - Latvia
hy-AM Armenian - Armenia lt Lithuanian
az

 

Azeri lt-LT Lithuanian - Lithuania
az-AZ-Cyrl Azeri (Cyrillic) - Azerbaijan

 

mk Macedonian
az-AZ-Latn Azeri (Latin) - Azerbaijan mk-MK

 

Macedonian - Former Yugoslav Republic of Macedonia
eu Basque ms Malay

 

eu-ES Basque - Basque ms-BN Malay - Brunei
be Belarusian ms-MY Malay - Malaysia
be-BY Belarusian - Belarus mr Marathi
bg Bulgarian mr-IN Marathi - India
bg-BG Bulgarian - Bulgaria mn Mongolian
ca Catalan mn-MN Mongolian - Mongolia
ca-ES Catalan - Catalan no Norwegian
zh-HK

 

Chinese - Hong Kong SAR nb-NO Norwegian (Bokm?l) - Norway
zh-MO Chinese - Macao SAR

 

nn-NO Norwegian (Nynorsk) - Norway
zh-CN Chinese - China pl

 

Polish
zh-CHS Chinese (Simplified) pl-PL Polish - Poland

 

zh-SG Chinese - Singapore pt Portuguese
zh-TW Chinese - Taiwan pt-BR Portuguese - Brazil
zh-CHT Chinese (Traditional) pt-PT Portuguese - Portugal
hr Croatian

 

pa Punjabi
hr-HR Croatian - Croatia pa-IN Punjabi - India
cs Czech ro Romanian
cs-CZ Czech - Czech Republic ro-RO Romanian - Romania
da

 

Danish ru Russian
da-DK Danish - Denmark

 

ru-RU Russian - Russia
div Dhivehi sa

 

Sanskrit
div-MV Dhivehi - Maldives sa-IN Sanskrit - India

 

nl Dutch sr-SP-Cyrl Serbian (Cyrillic) - Serbia
nl-BE Dutch - Belgium sr-SP-Latn Serbian (Latin) - Serbia
nl-NL Dutch - The Netherlands sk Slovak
en English sk-SK Slovak - Slovakia
en-AU English - Australia sl Slovenian
en-BZ English - Belize sl-SI Slovenian - Slovenia
en-CA English - Canada es Spanish
en-CB

 

English - Caribbean es-AR Spanish - Argentina
en-IE English - Ireland

 

es-BO Spanish - Bolivia
en-JM English - Jamaica es-CL

 

Spanish - Chile
en-NZ English - New Zealand es-CO Spanish - Colombia

 

en-PH English - Philippines es-CR Spanish - Costa Rica
en-ZA English - South Africa es-DO Spanish - Dominican Republic
en-TT English - Trinidad and Tobago es-EC Spanish - Ecuador
en-GB English - United Kingdom es-SV Spanish - El Salvador
en-US English - United States es-GT Spanish - Guatemala
en-ZW English - Zimbabwe es-HN Spanish - Honduras
et Estonian es-MX Spanish - Mexico
et-EE

 

Estonian - Estonia es-NI Spanish - Nicaragua
fo Faroese

 

es-PA Spanish - Panama
fo-FO Faroese - Faroe Islands es-PY

 

Spanish - Paraguay
fa Farsi es-PE Spanish - Peru

 

fa-IR Farsi - Iran es-PR Spanish - Puerto Rico
fi Finnish es-ES Spanish - Spain
fi-FI Finnish - Finland es-UY Spanish - Uruguay
fr French es-VE Spanish - Venezuela
fr-BE French - Belgium sw Swahili
fr-CA French - Canada sw-KE Swahili - Kenya
fr-FR French - France sv Swedish
fr-LU

 

French - Luxembourg sv-FI Swedish - Finland
fr-MC French - Monaco

 

sv-SE Swedish - Sweden
fr-CH French - Switzerland syr

 

Syriac
gl Galician syr-SY Syriac - Syria

 

gl-ES Galician - Galician ta Tamil
ka Georgian ta-IN Tamil - India
ka-GE Georgian - Georgia tt Tatar
de German tt-RU Tatar - Russia
de-AT German - Austria te Telugu
de-DE German - Germany te-IN Telugu - India
de-LI German - Liechtenstein th Thai
de-LU

 

German - Luxembourg th-TH Thai - Thailand
de-CH German - Switzerland

 

tr Turkish
el Greek tr-TR

 

Turkish - Turkey
el-GR Greek - Greece uk Ukrainian

 

gu Gujarati uk-UA Ukrainian - Ukraine
gu-IN Gujarati - India ur Urdu
he Hebrew ur-PK Urdu - Pakistan
he-IL Hebrew - Israel uz Uzbek
hi Hindi uz-UZ-Cyrl Uzbek (Cyrillic) - Uzbekistan
hi-IN Hindi - India uz-UZ-Latn Uzbek (Latin) - Uzbekistan
hu Hungarian vi Vietnamese

 


How to sort a generic List

May 19, 2009 09:34 by bryan

I came across a little issue today, in that I had an Interface object and I needed to be able to sort the list, I would normally implement the IComparable interface on the concreate type, but I don't have access to the concreate type in my case.

I tried several different methods in the end I ended up with using a delegate, and found in SimoneB Blog, which I have extracted the content below:

Sorting a generic List<T> is pretty straightforward if you know how to do it. With C# 2.0, anonymous methods come at hand, as well as the little known Comparison<T> delegate (check out this post for more information about this class as well as other useful classes new to C# 2.0).

Ok, let's suppose we have a product class (let me save some space by using C# 3.0 syntax).

 

class Product

{

    public int ProductID { get; set; }

    public string ProductName { get; set; }

    public decimal UnitPrice { get; set; }

}

When we have a list of products we may want to sort it on the ProductName property before displaying it to the user. This can be accomplished with the Sort method of the List<T> class, which defines several overloads. The most handy in this case is the Sort(Comparison<Product>) method and the result is easily achieved with a couple lines of code.

 

List<Product> products = new List<Product>();

 

products.Sort(delegate(Product p1, Product p2)

              {

                  return p1.ProductName.CompareTo(p2.ProductName);

              });

So far so good, but what if we need to sort our list in several places during the execution of our program? Do we have to write that code each time? Actually no, since we can use the parameterless Sort() method of our list class. What this method does is use the "default comparer" to sort the list. So what's this default comparer? It's the comparer that's automatically created if we implement the IComparable<T> interface. This way we can centralize the sorting logic into our class, and just call the parameterless Sort() method on it whenever we need it sorted on the ProductName property.

 

public class Product : IComparable<Product>

{

    [...]

 

    public int CompareTo(Product other)

    {

        return ProductName.CompareTo(other.ProductName);

    }

}

Ok, now what if we want to be able to sort it on the other two properties, ProductID and UnitPrice? Do we have to write an anonymous method each time as we did in the beginning? Of course no, since there's a useful trick which prevents us from needing to do that. We can define two static Comparer<Product> properties in our product class, and supply them as parameters to the Sort(Comparer<T>) method of our list whenever we need it sorted on something which is not the default sorting logic.

 

public class Product : IComparable<Product>

{

    [...]

 

    public static Comparison<Product> PriceComparison =

        delegate(Product p1, Product p2)

        {

            return p1.Price.CompareTo(p2.Price);

        };

 

    public static Comparison<Product> IDComparison =

        delegate(Product p1, Product p2)

        {

            return p1.ProductID.CompareTo(p2.ProductID);

        };

 

    [...]

}

Since they are static they can be used simply like so: products.Sort(Product.PriceComparison) or products.Sort(Product.IDComparison), which will respectively sort the list by price and id.

 

Below is the full code of the Product class.

 

public class Product : IComparable<Product>

{

    private int id;

    private string prodName;

    private decimal price;

 

    public static Comparison<Product> PriceComparison = delegate(Product p1, Product p2)

                                                        {

                                                            return p1.price.CompareTo(p2.price);

                                                        };

 

    public static Comparison<Product> IDComparison = delegate(Product p1, Product p2)

                                                     {

                                                         return p1.id.CompareTo(p2.id);

                                                     };

 

    public int ProductID

    {

        get { return id; }

        set { id = value; }

    }

 

    public string ProductName

    {

        get { return prodName; }

        set { prodName = value; }

    }

 

    public decimal UnitPrice

    {

        get { return price; }

        set { price = value; }

    }

 

    public Product(int id, string prodName, decimal price)

    {

        this.id = id;

        this.prodName = prodName;

        this.price = price;

    }

 

    #region IComparable<Product> Members

 

    public int CompareTo(Product other)

    {

        return ProductName.CompareTo(other.ProductName);

    }

 

    #endregion

 

    public override string ToString()

    {

        return string.Format("Id: {0} Name: {1} Price: {2}", id, prodName, price);

    }

}