Using LINQ to initialize DI Containers

Posted Sunday, March 09, 2008 by

Recently there have been some discussion on how to help initialize dependency injection containers. Ayende call this "Setting up Zero Fiction Projects" and uses the Boo language to create a DSL (Domain Specific Language) to specify components to be registered into the container. From hammet comes news around a fluent interface for adding components to Castle Windsor. The essence of both is to find all types in a given assembly that either implement a certain a certain interface or are a subclass of a layer supertype (I tend to have a ServiceBase that contains things Log and so on). We can use LINQ to achieve something similar to both the above approaches.

public static void RegisterControllers(params string[] assemblies)

{

    foreach(string assembly in assemblies)

    {

        IEnumerable<Type> controllers = from t in Assembly.Load(assembly).GetTypes()

                                        where t.Implements<IController>()

                                        select t;

 

        foreach(Type controller in controllers)

        {

            Container.AddComponentWithLifestyle(controller.FullName, controller, LifestyleType.Transient);

        }

    }

}

 

The above code iterates a list of assembly names and finds all types that implement the ASP.NET MVC IController interface. To increase the readability of the LINQ query I've used an extension method listed below.

public static bool Implements<T>(this Type type)

{

    return typeof(T).IsAssignableFrom(type);

}

 

The below code locates the first interface for the service and uses that as the service to register the type. Depending on how you create your types this may or may not be a good method. Using the Repository class I've described before doesn't allow this approach as it is the last interface that becomes the important one, however I've used this code to show some similar functionality as the examples above. Hope this helps someone.

public static void RegisterServices(params string[] assemblies)

{

    foreach(string assembly in assemblies)

    {

        var services = from t in Assembly.Load(assembly).GetTypes()

                       where t.GetInterfaces().Length > 0 && t.IsSubclassOf(typeof(ServiceBase))

                       let i = t.GetInterfaces()[0]

                       where !Container.Kernel.HasComponent(i)

                       select new

                       {

                           Interface = i.IsGenericType ? i.GetGenericTypeDefinition() : i,

                           Component = t

                       };

 

        foreach(var service in services)

        {

            Container.AddComponent(service.Interface.FullName, service.Interface, service.Component);

        }

    }

}

Using LINQ expressions to name Validation Rules

Posted Sunday, March 02, 2008 by

 In various places in code we want to use property names in our code, for instance validation or business rules are quick commonly named after the property they're validating. Usually you end up with code looking a little like this.

Rule<Person> rule = new Rule<Person>("FirstName");

 

As Ayende says "Strings are bad", there are typo issues and also they're immune to refactoring. So here's a quick way not to use them, I wouldn't call this fully fledged as we're not getting compile time checking yet. The key part to this code is taking an Expression rather than a Func, this allows us to examine the expressions in the lambda to get the property name.

public class Rule<T>

{

    private string name;

 

    public Rule(Expression<Func<T, object>> expression)

    {

        MemberExpression memberExpression = expression.Body as MemberExpression;

 

        name = memberExpression == null ? String.Empty : memberExpression.Member.Name;

    }

 

    public string Name

    {

        get

        {

            return name;

        }

    }

}

 

This gives the syntax for rule creation as follows.

Rule<Person> rule = new Rule<Person>(p => p.FirstName);

Specialised LINQ to SQL Repositories

Posted Saturday, February 09, 2008 by

 We finished off last time with creating a Repository<T> class and matching interface. This is a general workhorse of a class that allows such syntax as

IRepository<Item> repository = new Repository<Item>(new InMemoryUnitOfWork);
IEnumerable<Item> outOfStock = from i in repository where i.QuantityOnHand == 0 select i;
foreach(Item item in repository) { }

What I'd like however is to be able to encapsulate some of the more complex queries behind specialised repositories, these repositories can can then mocked with tools other than TypeMock and move some great interaction based testing. We'll start by moving the out of stock query above to an ItemRepository

public interface IItemRepository
{
IEnumerable<Item> GetOutOfStockItems();
}
public class ItemRepository : Repository<Item>, IItemRepository
{
public ItemRepository(IUnitOfWork unitOfWork) : base(unitOfWork) { }
public IEnumerable<Item> GetOutOfStockItems()
{
return outOfStock = from i in this where i.QuantityOnHand == 0 select i;
}
}

The LINQ query does look a little odd since we're querying the repository directly, in order to make this a little more readable I add a property

IQueryable<Item> Items
{
get { return this; }
}

to make the LINQ query

from i in Items where i.QuantityOnHand == 0 select i;

Interestingly because IItemRepository doesn't implement IRepository<Item> we lose externally the ability to execute LINQ queries against it (this could be desired through). I prefer altering it however to

public interface IItemRepository : IRepository<Item>

in order the use of LINQ and normal repository actions throughout the system while only refactoring complex or commonly used queries into the repository itself.

Domain Driven Design Repositories in LINQ to SQL

Posted Tuesday, February 05, 2008 by

Lately I've been working with NHibernate behind a domain driven design style repository interface, this allows for easily testability as I can create mock repositories using Rhino Mocks and give my services prepackaged results for testing purposes.

This has worked out great, in combination with NHibernate Query Generator I get some very readable code. After deciding that my next pet project would include LINQ to SQL I wanted to achieve the same results with regard to testability without reliance on an external database.

From some reading around the web it looked like doing interaction style testing on LINQ style queries would be difficult due to extension methods being static and the like (I realise TypeMock gets around this due to using the Profiler API rather than dynamic proxies). But at the minimum I wanted to provide prepackaged results and the ability to create aggregate repositories with specialised queries that could be mocked and tested.

This really isn't persistence ignorance as our model is still tied LINQ to SQL via the attributes, but I still achieve some worthwhile goals even if I'm not being completely ignorant.

The two best pieces of work I could find on the subject were K. Scott Allen's "Trying Out Persistence Ignorance With LINQ" and "Being Ignorant with LINQ to SQL" by Ian Cooper. I preferred the formers approach the best and really this work is just wrapping up his work with some personal alterations.

LINQ queries work by a QueryProvider resolving an expression, LINQ to SQL resolves the expression to SQL whereas something like LINQ to Amazon resolves the same expression to a web-service call. In order to achieve our testing goals the QueryProvider that ultimately resolves the given expression is switched. For our in-memory repository we'll be using a List<T> and therefore LINQ to Objects.

We begin by defining out IUnitOfWork, this will create data sources that will represent either a table in LINQ to SQL or a List<T> in LINQ to Objects as well as provide a life cycle for our underlying DataContext. Our InMemoryUnitOfWork is storing it's created data sources so that repeated creations of a data source will always have the same underlying list to mimic the behavior of our SqlUnitOfWork which is always using the same DataContext.

public interface IUnitOfWork : IDisposable
{
IDataSource<T> GetDataSource<T>() where T : class;
void SubmitChanges();
}
public class InMemoryUnitOfWork : IUnitOfWork
{
private Hashtable dataSources = new Hashtable();
public IDataSource<T> GetDataSource<T>() where T : class
{
if(!dataSources.ContainsKey(typeof(T)))
dataSources.Add(typeof(T), new InMemoryDataSource<T>());
return dataSources[typeof(T)] as InMemoryDataSource<T>;
}
public void SubmitChanges()
{
}
public void Dispose()
{
}
}
public class SqlUnitOfWork : IUnitOfWork
{
private DataContext context;
public SqlUnitOfWork(DataContext context)
{
if(context == null)
throw new ArgumentNullException("context");
this.context = context;
}
public IDataSource<T> GetDataSource<T>() where T : class
{
return new SqlDataSource<T>(context);
}
public void SubmitChanges()
{
context.SubmitChanges();
}
public void Dispose()
{
context.Dispose();
}
}

Now to define our IDataSource, it inherits IQueryable<T> to allow it to be queried using LINQ. Part of the IQueryable<T> interface is the property Provider, each data source will route all LINQ queries to their underlying Provider to be appropriately resolved. I've also defined some simple Save, Update and Delete methods, I'm doing this rather than implementing something like ITable because I want to keep the repository simple and fairly similar to NHibernate.

public interface IDataSource<T> : IQueryable<T> where T : class
{
void Update(T entity);
void Update(IEnumerable<T> entities);
void Delete(T entity);
void Delete(IEnumerable<T> entities);
void Save(T entity);
void Save(IEnumerable<T> entities);
}
public class InMemoryDataSource<T> : IDataSource<T> where T : class
{
private List<T> dataSource;
public InMemoryDataSource()
: this(new List<T>())
{
}
public InMemoryDataSource(List<T> dataSource)
{
if(dataSource == null)
throw new ArgumentNullException("dataSource");
this.dataSource = dataSource;
}
public IEnumerator<T> GetEnumerator()
{
return dataSource.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public Type ElementType
{
get
{
return dataSource.AsQueryable<T>().ElementType;
}
}
public Expression Expression
{
get
{
return dataSource.AsQueryable<T>().Expression;
}
}
public IQueryProvider Provider
{
get
{
return dataSource.AsQueryable<T>().Provider;
}
}
public void Delete(T entity)
{
dataSource.Remove(entity);
}
...
}
public class SqlDataSource<T> : IDataSource<T> where T : class
{
private Table<T> table;
public SqlDataSource(DataContext context)
{
if(context == null)
throw new ArgumentNullException("context");
table = context.GetTable<T>();
}
public IEnumerator<T> GetEnumerator()
{
return table.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public Type ElementType
{
get
{
return table.AsQueryable<T>().ElementType;
}
}
public Expression Expression
{
get
{
return table.AsQueryable<T>().Expression;
}
}
public IQueryProvider Provider
{
get
{
return table.AsQueryable<T>().Provider;
}
}
public void Delete(T entity)
{
table.DeleteOnSubmit(entity);
}
...
}

An IRepository<T> is simply another data source but I've created this interface anyway in order to keep everything linked up with domain driven design concepts and for future extensions. I've now also created a base Repository<T> class that takes a given IUnitOfWork and then uses it's given data source for all it's operations. We can NOW create a repository with an in memory data source, add items to it before passing it to services under test. While in our live system use a LINQ to SQL DataContext to send all our queries to SQL Server.

public interface IRepository<T> : IDataSource<T> where T : class
{
}
public class Repository<T> : IRepository<T> where T : class
{
private IDataSource<T> dataSource;
public Repository(IUnitOfWork unitOfWork)
{
if(unitOfWork == null)
throw new ArgumentNullException("unitOfWork");
dataSource = unitOfWork.GetDataSource<T>();
}
public void Update(T entity)
{
dataSource.Update(entity);
}
public void Update(IEnumerable<T> entities)
{
dataSource.Update(entities);
}
public void Delete(T entity)
{
dataSource.Delete(entity);
}
public void Delete(IEnumerable<T> entities)
{
dataSource.Delete(entities);
}
public void Save(T entity)
{
dataSource.Save(entity);
}
public void Save(IEnumerable<T> entities)
{
dataSource.Save(entities);
}
public IEnumerator<T> GetEnumerator()
{
return dataSource.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public Type ElementType
{
get
{
return dataSource.ElementType;
}
}
public Expression Expression
{
get
{
return dataSource.Expression;
}
}
public IQueryProvider Provider
{
get
{
return dataSource.Provider;
}
}
}
[Test]
public void LinqQueryFromInMemoryUnitOfWork()
{
IRepository<Item> repository = new Repository<Item>(new InMemoryUnitOfWork());
repository.Save(new Item() { Name = "Item1", QuantityOnHand = 10 });
repository.Save(new Item() { Name = "Item2", QuantityOnHand = 0 });
IEnumerable<Item> outOfStockItems = from item in repository where item.QuantityOnHand == 0 select item;
CollectionAssert.AreCountEqual(1, outOfStockItems.ToList());
}

Once I get some appropriate hosting sorted out I'll post the full code and unit tests. Next time, creating specialised aggregate repositories...

Page 2 of 2<12

Professional Windows App Development