I was intrigued by the possibilities raised by your question, so I did some research on how to create repository proxies using either Castles DynamicProxy or the Reflection.Emit classes.
Using the following repository and domain classes (I extended the script to allow repositories to return collections with a strong type):
public interface IRepository<T> { IEnumerable<T> All { get; } } public abstract class Repository<T> : IRepository<T> { public IEnumerable<T> All { get { return new T[0]; } } } public interface IFooRepository : IRepository<Foo> { } public class Foo { }
To create a proxy equivalent
public class FooRepository : Repository<Foo>, IFooRepository { }
when using DynamicProxy:
DefaultProxyBuilder proxyBuilder = new DefaultProxyBuilder(); Type baseType = typeof(Repository<>).MakeGenericType(typeof(Foo)); Type[] intefacesImplemented = new Type[] { typeof(IFooRepository) }; Type proxy = proxyBuilder.CreateClassProxyType(baseType, intefacesImplemented, ProxyGenerationOptions.Default);
When using Reflection.Emit:
Type baseType = typeof(Repository<>).MakeGenericType(typeof(Foo)); Type repositoryInteface = typeof(IFooRepository); AssemblyName asmName = new AssemblyName( string.Format("{0}_{1}", "tmpAsm", Guid.NewGuid().ToString("N")) ); // create in memory assembly only AssemblyBuilder asmBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(asmName, AssemblyBuilderAccess.Run); ModuleBuilder moduleBuilder = asmBuilder.DefineDynamicModule("core"); string proxyTypeName = string.Format("{0}_{1}", repositoryInteface.Name, Guid.NewGuid().ToString("N")); TypeBuilder typeBuilder = moduleBuilder.DefineType(proxyTypeName); typeBuilder.AddInterfaceImplementation(repositoryInteface); typeBuilder.SetParent(baseType); Type proxy = typeBuilder.CreateType();
Then you can register them in the IOC container and use them as usual: (in this case, Windsor):
WindsorContainer container = new WindsorContainer(); container.Register(Component.For<IFooRepository>().Forward(proxy)); IFooRepository repository = container.Resolve<IFooRepository>(); IEnumerable<Foo> allFoos = repository.All;
Both Reflection.Emit and DynamicProxy can be configured to use constructors other than the default.
If you are interested theres an excellent tutorial in DynamicProxy, and the documentation for the Reflection.Emit classes can be found.