Posted Sunday, March 09, 2008 by Nigel Sampson
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);
}
}
}
Posted Sunday, March 02, 2008 by Nigel Sampson
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);
Posted Saturday, February 09, 2008 by Nigel Sampson
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.
Posted Tuesday, February 05, 2008 by Nigel Sampson
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...