Categories
Computers and Internet

Referencing a .NET assembly in a compile time safe manner

If you need to provide a System.Reflection.Assembly instance to an API [1], there are several mechanisms for doing so. They roughly split into two camps:

  • Run-time assembly loading
  • Assemblies known at compile time

The run-time assembly loading includes scenarios such as having a plug-in architecture where the code being referenced cannot be known at the time of compilation.

For the other camp, if we know exactly which assembly we need to reference at compile time we have a couple of options. We can use the name of the assembly as a string like so:

Assembly.Load(“MyCompany.Util”);

(Note that if the assembly is already loaded the runtime will just return the loaded instance of that assembly and won’t attempt to load it again.)

Alternatively we can use a type from that assembly like so:

Assembly.GetAssembly(typeof(MyCompany.Util.AnyOldClass);

The problem with the assembly name string approach is that there is no compile time checking. The typeof approach allows for compile time checking but introduces an artificial dependency in the calling code on a class that it only needs for the purposes of getting the assembly. This calling code is then subject to any renaming or removal of that class when in reality it cares only about the assembly and not the type.

The solution I’ve gone for is to create a static, empty class with a similar name to the assembly in the root of the default namespace of the assembly I wish to reference and use this in the typeof:

using MyCompany.Util;
/* … */
Assembly.GetAssembly(typeof(MyCompanyUtil));

This provides us with a compiler error if the assembly reference is dropped or the assembly is renamed. It will take part in any necessary refactoring operations and is not dependent on irrelevant types.

 

[1] Examples include Autofac’s MVC and WebApi integration: ContainerBuilder.RegisterControllers & ContainerBuilder.RegisterApiControllers

Advertisement
Categories
Computers and Internet laZook

Tightening Injected Dependencies on Entity Framework

Dependency injection as a pattern provides a lot of useful nudges to get you to produce easily readable and maintainable code. One way in which it does this is to make dependencies explicit so you can see exactly what services a class requires. When using Entity Framework most people are passing the whole context through as a dependency. This post explores an alternative to this approach that provides more clarity of the client code’s use of the context.

We’ve been coding with Entity Framework here at laZook for a while now, using the code first workflow. We’re using Autofac as our dependency injection framework. We inject dependencies into the constructor so that there is one clear place to view a class’s dependencies.

We used to inject the whole DbContext derived class into each type that needed to do anything with the context, e.g. add entities or save changes. This was fairly easy to do, but lead to some confusion. Let’s look at an example program using this technique:

public class Coordinator
{
private readonly IMyContext _myContext;
private readonly WidgetGenerator _widgetGenerator;
private readonly WotsitGenerator _wotsitGenerator;
public Coordinator(
IMyContext myContext,
WidgetGenerator widgetGenerator,
WotsitGenerator wotsitGenerator)
{
_myContext = myContext;
_widgetGenerator = widgetGenerator;
_wotsitGenerator = wotsitGenerator;
}
public void DoStuff()
{
_widgetGenerator.GenerateWidgets();
_wotsitGenerator.GenerateWotsits();
_myContext.SaveChanges();
}
}
public class WotsitGenerator
{
private readonly IMyContext _myContext;
public WotsitGenerator(IMyContext myContext)
{
_myContext = myContext;
}
public void GenerateWotsits()
{
if (DateTime.Now.DayOfWeek == DayOfWeek.Friday)
{
throw new Exception("No wotsit generation on Fridays!");
}
_myContext.Wotsits.Add(new Wotsit());
}
}
public class WidgetGenerator
{
private readonly IMyContext _myContext;
public WidgetGenerator(IMyContext myContext)
{
_myContext = myContext;
}
public void GenerateWidgets()
{
_myContext.Widgets.Add(new Widget());
_myContext.SaveChanges();
}
}
public class MyContext : DbContext, IMyContext
{
public IDbSet<Widget> Widgets { get; set; }
public IDbSet<Wotsit> Wotsits { get; set; }
}
public interface IMyContext
{
IDbSet<Widget> Widgets { get; set; }
IDbSet<Wotsit> Wotsits { get; set; }
int SaveChanges();
}
view raw MyContext.cs hosted with ❤ by GitHub
class Program
{
static void Main(string[] args)
{
using (var container = CreateContainer())
{
var coordinator = container.Resolve<Coordinator>();
coordinator.DoStuff();
}
}
private static IContainer CreateContainer()
{
var containerBuilder = new ContainerBuilder();
containerBuilder.RegisterType<MyContext>().AsImplementedInterfaces().InstancePerLifetimeScope();
containerBuilder.RegisterType<Coordinator>();
containerBuilder.RegisterType<WotsitGenerator>();
containerBuilder.RegisterType<WidgetGenerator>();
return containerBuilder.Build();
}
}
view raw Program.cs hosted with ❤ by GitHub

In this simple example we saw that the Coordinator class was calling upon a couple of worker classes and then persisting any changes. The worker classes were adding the entities to their respective DbSets.

There is a problem with the code, though. If it’s a Friday, no Wotsits will be made. The code will exit due to the exception. If you were looking only at the Coordinator and WotsitGenerator code, you’d be forgiven for thinking that there was a single unit of work and it would not be committed. It looks like the Coordinator is responsible for the SaveChanges call. However, a closer look at the WidgetGenerator reveals a call to SaveChanges after it has created a widget.

It’s a simple example, but where SaveChanges is buried in larger code it can be difficult to work out what is being committed and what isn’t.

What to do about this? One answer is to ensure that SaveChanges is only ever called at the very top level as the last action before the end of the program (in this example) or page request / job execution / button click handler. This works, but is somewhat limiting. What if you want to perform multiple SaveChanges to checkpoint during a long running operation? What if the success or failure of one SaveChanges determines whether or not another unit of work is embarked upon?

We need to make it clear who owns the responsibility for initiating completion of the unit of work.

The solution we’ve come up with is to create an ICompleteUnitOfWork interface that contains the SaveChanges method and have the context implement this interface. This interface is then declared as a dependency for the class that has the responsibility of calling SaveChanges. This allows us to glance at a class constructor and see whether that class owns the responsibility for completing the unit of work. Elsewhere we inject IDbSet<TEntity> instances. This helps us see which entities (or at least which aggregate roots) a class is involved in reading or editing.

Here’s the same code with the new dependencies and the errant SaveChanges in WidgetGenerator removed. We can clearly tell that WidgetGenerator does not call SaveChanges by seeing that it only takes a dependency on IDbSet<Widget>.

public class Coordinator
{
private readonly ICompleteUnitOfWork _unitOfWorkCompleter;
private readonly WidgetGenerator _widgetGenerator;
private readonly WotsitGenerator _wotsitGenerator;
public Coordinator(
ICompleteUnitOfWork unitOfWorkCompleter,
WidgetGenerator widgetGenerator,
WotsitGenerator wotsitGenerator)
{
_unitOfWorkCompleter = unitOfWorkCompleter;
_widgetGenerator = widgetGenerator;
_wotsitGenerator = wotsitGenerator;
}
public void DoStuff()
{
_widgetGenerator.GenerateWidgets();
_wotsitGenerator.GenerateWotsits();
_unitOfWorkCompleter.SaveChanges();
}
}
public class WotsitGenerator
{
private readonly IDbSet<Wotsit> _wotsitDbSet;
public WotsitGenerator(IDbSet<Wotsit> wotsitDbSet)
{
_wotsitDbSet = wotsitDbSet;
}
public void GenerateWotsits()
{
if (DateTime.Now.DayOfWeek == DayOfWeek.Friday)
{
throw new Exception("No wotsit generation on Fridays!");
}
_wotsitDbSet.Add(new Wotsit());
}
}
public class WidgetGenerator
{
private readonly IDbSet<Widget> _widgetDbSet;
public WidgetGenerator(IDbSet<Widget> widgetDbSet)
{
_widgetDbSet = widgetDbSet;
}
public void GenerateWidgets()
{
_widgetDbSet.Add(new Widget());
}
}
public class MyContext : DbContext, ICompleteUnitOfWork
{
public IDbSet<Widget> Widgets { get; set; }
public IDbSet<Wotsit> Wotsits { get; set; }
}
public interface ICompleteUnitOfWork
{
int SaveChanges();
}
view raw MyContext.cs hosted with ❤ by GitHub
class Program
{
static void Main(string[] args)
{
using (var container = CreateContainer())
{
var coordinator = container.Resolve<Coordinator>();
coordinator.DoStuff();
}
}
private static IContainer CreateContainer()
{
var containerBuilder = new ContainerBuilder();
containerBuilder.RegisterType<MyContext>().AsSelf().AsImplementedInterfaces().InstancePerLifetimeScope();
containerBuilder.Register(c => c.Resolve<MyContext>().Widgets);
containerBuilder.Register(c => c.Resolve<MyContext>().Wotsits);
containerBuilder.RegisterType<Coordinator>();
containerBuilder.RegisterType<WotsitGenerator>();
containerBuilder.RegisterType<WidgetGenerator>();
return containerBuilder.Build();
}
}
view raw Program.cs hosted with ❤ by GitHub

What are the problems with this approach?

There are some usage patterns of Entity Framework that it doesn’t support too well, but it can be extended to do so. For example, there is no way to get at the DbContext.Entry method for attaching objects and setting their state. You could introduce another interface for this, IManageUnitOfWorkObjectState, but it feels clunky.

Also, injecting the IDbSets is a good first step, but I actually prefer creating some repositories on top of the IDbSets as it better allows for caching and encapsulation of common queries.

I’m interested in any development suggestions or criticisms of the ideas. Let me know here or on Twitter.