23 September 2010

LINQ: Distinct with projection

In recent blog post Ed suggested a few useful extension methods missing in LINQ.

Drawback of that implementation is the need to specify lambda taking two arguments in order to create a comparer.

Here's a simpler approach.

First of all, usage:
values.Distinct(v => v.Id)

implementation:

public static class EnumerableExtensions
{
    public static IEnumerable<T> Distinct<T, TId>(this IEnumerable<T> values, Func<T, TId> projection)
        where TId : IEquatable<TId>
    {
        return values.Distinct(new ProjectingEqualityComparer<T, TId>(projection));
    }

    class ProjectingEqualityComparer<T, TId> : IEqualityComparer<T>
        where TId : IEquatable<TId>
    {
        readonly Func<T, TId> projection;

        public ProjectingEqualityComparer(Func<T, TId> projection)
        {
            this.projection = projection;
        }

        public bool Equals(T x, T y)
        {
            return EqualityComparer<TId>.Default.Equals(projection(x), projection(y));
        }

        public int GetHashCode(T obj)
        {
            return EqualityComparer<TId>.Default.GetHashCode(projection(obj));
        }
    }
}

05 September 2010

Mapping enums with Automapper

If no map is created then first name-based then value-based mapping is applied.

If map is created value-based mapping is used.

Results only differ for values with same names but different values.

enum One { Value = 3, Name1 = 7, Unique1 = 8 }
enum Two { Value = 5, Name2 = 7, Unique2 = 9 }

static void PrintMapped(One one)
{
    Console.WriteLine("{0,7} --> {1}", one, Mapper.Map<One, Two>(one));
}

static void PrintAllMappings()
{
    Console.ForegroundColor = ConsoleColor.Cyan;
    Console.WriteLine("{0,7} --> {1}", "One", "Two");

    Console.ForegroundColor = ConsoleColor.Gray;
    PrintMapped((One)1);
    PrintMapped(One.Value);
    PrintMapped(One.Name1);
    PrintMapped(One.Unique1);

    Console.WriteLine();
}

static void Main(string[] args)
{
    PrintAllMappings();

    Mapper.CreateMap<One, Two>();
    PrintAllMappings();

    Console.WriteLine("Press ENTER to finish");
    Console.ReadLine();
}

Output:
    One --> Two
      1 --> 1
  Value --> Value
  Name1 --> Name2
Unique1 --> 8

    One --> Two
      1 --> 1
  Value --> 3
  Name1 --> Name2
Unique1 --> 8

29 August 2010

GridView image column

public class GridViewImageColumn : GridViewColumn
{
    readonly FrameworkElementFactory elementFactory = new FrameworkElementFactory(typeof(Image));

    public BindingBase SourceBinding
    {
        set { elementFactory.SetBinding(Image.SourceProperty, value); }
    }

    public GridViewImageColumn()
    {
        CellTemplate = new DataTemplate { VisualTree = elementFactory };
    }
}