Skip to content

Instantly share code, notes, and snippets.

@JasonOffutt
Created August 2, 2012 16:02
Show Gist options
  • Save JasonOffutt/3238169 to your computer and use it in GitHub Desktop.
Save JasonOffutt/3238169 to your computer and use it in GitHub Desktop.
Proposal for adding dependency injection of IRepository<T> into Rock
<configuration>
<appSettings>
<clear/>
<add key="RepositoryType" value="Rock.Tests.Fakes.FakeAttributeRepository,Rock.Tests"/>
</appSettings>
</configuration
public class Page : ModelWithAttributes<Page>, IExportable
{
// ...
// Here's a very simplified/non-recursive example of usage that causes
// a problem. ModelWithAttributes<Page> has a Service<Page> that ultimately
// would be instantiated as an EFRepository<Page> rather than something that
// can be controlled from outside (e.g. config settings or dependency injection).
public object ExportObject()
{
return this.ToDynamic();
}
public string ExportJson()
{
return this.ExportObject.ToJson();
}
}
public class PageTests
{
public class TheExportJsonMethod
{
// Here's an example of a unit test that should be isolated from
// the database. This test should be able to run without having
// to rely on any external component, like a database, web service, etc.
[Fact]
public void ShouldNotBeEmpty()
{
var page = new Page() { Name = "FooPage" };
var result = page.ExportJson();
Assert.NotEmpty(result);
}
}
}
// Here's the proposed implementation of RepositoryFactory. Using config settings
// is probably the quickest and easiest solution. I've also implemented something
// similar in Grassroots that uses MEF. Both approaches add a bit of overhead, but
// should give us a lot of flexibility. And due to how heavily things get cached,
// we shouldn't notice much of a performance hit.
public static class RepositoryFactory
{
public static IRepository<T> FindRepository<T>() where T : class
{
// First, check the config file to see if anything special needs to be done...
var repositoryType = ConfigurationManager.AppSettings["RepositoryType"];
// If not, load the usual EFRepository...
if (string.IsNullOrEmpty(repositoryType))
{
return new EFRepository<T>();
}
// Otherwise create an instance of the type defined in the config file.
var setting = repositoryType.Split( new[] { ',' } );
var classPath = setting[0].Trim();
var assemblyName = setting[1].Trim();
return (IRepository<T>) Activator.CreateInstance( assemblyName, classPath ).Unwrap();
}
}
public class Service<T>
{
private IRepository<T> _repository;
protected IRepository<T>
{
get { return _repository; }
}
// This line is giving me a little grief. There is a hard dependency on
// EFRepository, even though there's a constructor that accepts an
// IRepository<T> arg, there's no good way for to control how it gets
// instantiated.
public Service<T>() // : this(new EFRepository<T>())
{
_repository = RepositoryFactory.FindRepository<T>();
}
public Service<T>(IRepository<T> repository)
{
_repository = repository;
}
// ...
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment