Monday, November 28, 2011

Using Unity to Resolve Instances based on condition


Unity is a lightweight, extensible dependency injection container with support for nested containers that stores registrations and mappings between types and can instantiate the appropriate concrete types on demand. Identification of the registrations in unity can be done using a type and a name (optional).
You can use unity to register multiple implementations of the same type and later resolve the actual instance by passing the name for identifying the actual implementation. In this post we'll see how to resolve the instances registered in unity application block conditionally.
For e.g. I have created a sample interface and implementations as given below
public interface IMyObject
{
    string DoSomething();
}

public class MyObjectFirstImplementation : IMyObject
{
    public string DoSomething()
    {
        return "First";
    }
}

public class MyObjectSecondImplementation : IMyObject
{
    public string DoSomething()
    {
        return "Second";
    }
}

The registration of these components are done like
container
    .RegisterType<IMyObject, MyObjectFirstImplementation>(DependencyRegistrationKeys.FirstImplementation)
    .RegisterType<IMyObject, MyObjectSecondImplementation>(DependencyRegistrationKeys.SecondImplementation);

public static class DependencyRegistrationKeys
{
    public const string FirstImplementation = "FIRST_IMPLEMENTATION";
    public const string SecondImplementation = "SECOND_IMPLEMENTATION";
}

The factory class has a create method that accepts and object key to resolve the actual instances
public class MyObjectFactory
{
    public IMyObject Create(string objectKey)
    {
        return Container.Instance.Resolve<IMyObject>(objectKey);
    }
}

Tests
[TestMethod]
public void CreateMethodShouldReturnTheObjectImplementationBasedOnConditionPassed()
{
    var factory = new MyObjectFactory();
    var myObject = factory.Create(DependencyRegistrationKeys.FirstImplementation);

    Assert.IsInstanceOfType(myObject, typeof(MyObjectFirstImplementation));
}

Monday, November 21, 2011

The Specification Pattern - A Generic implementation


In this post I’m going to create a generic implementation of the specification pattern.
The central idea of Specification is to separate the statement of how to match a candidate, from the candidate object that it is matched against. As well as its usefulness in selection, it is also valuable forvalidation and for building to order. Every specification implementation needs to specify a method that evaluates a condition mentioned in the interface Ispecification as given below.
public interface ISpecification where T : class
{
    Expression<Funcbool>> SatisfiedBy();
}
The generic specification class implements the Ispecification interface as
public sealed class Specification : ISpecification where T : class
{
    readonly Expression<Funcbool>> _matchingCriteria;

    public Specification(Expression<Funcbool>> matchingCriteria)
    {
        if (matchingCriteria == null) throw new ArgumentNullException("matchingCriteria");

        _matchingCriteria = matchingCriteria;
    }

    public Expression<Funcbool>> SatisfiedBy()
    {
        return _matchingCriteria;
    }
}
Using this implementation we can create the AND specification as
public sealed class AndSpecification : ISpecification where T : class
{
    private readonly ISpecification _rightSideSpecification;
    private readonly ISpecification _leftSideSpecification;

    public AndSpecification(ISpecification leftSide, ISpecification rightSide)
    {
        if (leftSide == null) throw new ArgumentNullException("leftSide");
        if (rightSide == null) throw new ArgumentNullException("rightSide");

        _leftSideSpecification = leftSide;
        _rightSideSpecification = rightSide;
    }

    public ISpecification LeftSideSpecification
    {
        get { return _leftSideSpecification; }
    }

    public ISpecification RightSideSpecification
    {
        get { return _rightSideSpecification; }
    }

    public Expression<Funcbool>> SatisfiedBy()
    {
        var left = _leftSideSpecification.SatisfiedBy();
        var right = _rightSideSpecification.SatisfiedBy();

        return (left.And(right));
    }
}

The AND method is an extension method on the ISpecification and Expression<Funcbool>>  types
public static ISpecification AND(this ISpecification leftSpecification, ISpecification rightSpecification) where T : class
{
    return new AndSpecification(leftSpecification, rightSpecification);
}

public static Expression Compose(this Expression first, Expression second,
                                        Func<Expression, Expression, Expression> merge)
{
    var map =
        first.Parameters.Select((f, i) => new {f, s = second.Parameters[i]}).ToDictionary(p => p.s, p => p.f);
    var secondBody = ExpressionTreeParameterReplacer.ReplaceParameters(map, second.Body);
    return Expression.Lambda(merge(first.Body, secondBody), first.Parameters);
}

public static Expression<Funcbool>> AND(this Expression<Funcbool>> first,
                                                Expression<Funcbool>> second)
{
    return first.Compose(second, Expression.And);
}

The ExpressionTreeVisitor implementation to replace and join the parameters for these extension methods
public sealed class ExpressionTreeParameterReplacer : ExpressionVisitor
{
    private readonly Dictionary<ParameterExpression, ParameterExpression> _map;

    public ExpressionTreeParameterReplacer(Dictionary<ParameterExpression, ParameterExpression> map)
    {
        _map = map ?? new Dictionary<ParameterExpression, ParameterExpression>();
    }

    public static Expression ReplaceParameters(Dictionary<ParameterExpression, ParameterExpression> map,
                                                Expression exp)
    {
        return new ExpressionTreeParameterReplacer(map).Visit(exp);
    }

    protected override Expression VisitParameter(ParameterExpression p)
    {
        ParameterExpression replacement;
        if (_map.TryGetValue(p, out replacement))
            p = replacement;

        return base.VisitParameter(p);
    }
}

Now let’s look at a sample using the specification pattern implementation.
public class Customer
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string UserName { get; set; }
    public DateTime DateOfJoining { get; set; }
    public Address Address { get; set; }
}
public class Address
{
    public string Street { get; set; }
    public string State { get; set; }
    public string City { get; set; }
    public string Country { get; set; }
}

public class CountryNameSpecification  : ISpecification<Customer>
{
    private readonly string _countryName;

    public CountryNameSpecification(string countryName)
    {
        _countryName = countryName;
    }

    public Expression<Func<Customer, bool>> SatisfiedBy()
    {
        return new Specification<Customer>(c => c.Address.Country.Contains(_countryName)).SatisfiedBy();
    }
}

public class CustomerFirstNameSpecification :ISpecification<Customer>
{
    private readonly string _firstName;

    public CustomerFirstNameSpecification(string firstName)
    {
        _firstName = firstName;
    }

    public Expression<Func<Customer, bool>> SatisfiedBy()
    {
        return new Specification<Customer>(c => c.FirstName.Equals(_firstName)).SatisfiedBy();
    }
}

[TestMethod]
public void AndSpecificationShouldSatisfyIfBothExpressionsSatisfiesTheCondition()
{
    var customers = GetAllCustomers();

    var fooCountrySpecification = new CountryNameSpecification("Foo");
    var customerFirtNameSpecification = new CustomerFirstNameSpecification("Foo4");

    var andSpecification = fooCountrySpecification.AND(customerFirtNameSpecification);

    var results = customers.Where(andSpecification.SatisfiedBy());
    Assert.IsTrue(results.ToList().All(c => c.Address.Country.Contains("Foo") && c.FirstName.Equals("Foo4")));
}

[TestMethod]
public void OrSpecificationShouldSatisfyIfOnOfTheConditionsSatisfiesTheSet()
{
    var customers = GetAllCustomers();

    var fooCountrySpecification = new CountryNameSpecification("Foo");
    var abcCountrySpecification = new CountryNameSpecification("Abc");
    var pqrCountrySpecification = new CountryNameSpecification("Pqr");


    var orSpecification = fooCountrySpecification.OR(abcCountrySpecification).OR(pqrCountrySpecification);

    var results = customers.Where(orSpecification.SatisfiedBy());
    Assert.IsTrue(results.Count() == customers.Count());
}

Where GetAllCustomers return an Iqueryable resultset of customers with addresses.