Lazy loading property with Castle.DynamicProxy2
Today I will solve a problem concerning single responsibility principle and lazy loading properties using Castle DynamicProxy. My example application is a simple bookstore, that can display books from an XML.
IList<Author> GetAuthorsForBook(string isbn);
}
Because the Author object would require a JOIN, we would like to lazy load the values - meaning, when we access the property it will be loaded with values from the datasource.
Castle.DynamicProxy2
Download the dynamic proxy and reference it in your project.
Now create a ProxyBuilder that will be responsible for creating proxies instances for the Book class. It is also possible to create proxies from classes but that is something you may discover by yourself.
public class ProxyBuilder : IProxyBuilder { private readonly IInterceptor[] interceptors; private readonly ProxyGenerator proxyGenerator;
public ProxyBuilder(IInterceptor[] interceptors)
: this(interceptors, new ProxyGenerator())
{
}
public ProxyBuilder(IInterceptor[] interceptors, ProxyGenerator proxyGenerator)
{
this.interceptors = interceptors;
this.proxyGenerator = proxyGenerator;
}
public virtual T ProxyFromClass<T>() where T : class
{
return proxyGenerator.CreateClassProxy<T>(interceptors);
}
}
If this where a larger application I would use a DI framework and register different instances of IProxyGenerator, for example.
container.Register<IProxyBuilder>("LazyAuthors", new[] { new LazyLoadAuthorsInterceptor() });
Our implementation of the interceptor that will be triggered on every virtual member of the class where it's put.
public LazyLoadAuthorsInterceptor(IStoreRepository repository)
{
this.repository = repository;
}
public void Intercept(IInvocation invocation)
{
if (invocation.Method.Name == MethodName)
{
var isbn = ((Book) invocation.InvocationTarget).Isbn;
invocation.ReturnValue = repository.GetAuthorsForBook(isbn);
}
}
}
Now we can create a proxy class of book, and when we call the Authors property, the authors will be loaded and returned from IStoreRepository.
// Will call IStoreRepository.GetAuthorsForBook var authors = book.Authors;
You may get the code for this here, or you may download it as a zip package.