3
votes

I am trying to register a Generic Repository in unity. I would prefer to do this in the bootstrapper using reflection.

I have successfully implemented and tested this:

container.RegisterType(typeof(MyDll.Repositories.IRepository<>), typeof(MyDll.Repositories.Repository<>), "MyDllRepository");

Then resolving:

var result = target.Resolve(typeof(My.Repositories.IRepository<MyClass>), "MyDllRepository");

Works great. What I don't like is that I need to reference MyDll explicitly in the Bootstrapper solution.

When I try and register the Repository automatically using reflection within my Bootstrapper like so:

private void RegisterDlls(String assembly)
    {
        var currentAssembly = Assembly.LoadFrom(assembly);
        var assemblyTypes = currentAssembly.GetTypes();

        var baseName = GetBaseName(currentAssembly.FullName);

        foreach (var assemblyType in assemblyTypes)
        {
            if (assemblyType.IsInterface)
            {
                continue;
            }

            if (assemblyType.FullName.EndsWith("Service"))
            {
                foreach (var requiredInterface in assemblyType.GetInterfaces())
                {
                    if (requiredInterface.FullName.EndsWith("Service"))
                    {
                        var typeFrom = assemblyType.GetInterface(requiredInterface.Name);
                        var typeTo = assemblyType;
                        RegisterType(typeFrom, typeTo, true, typeTo.Name);
                    }
                }
            }

        if (assemblyType.Namespace.EndsWith("Repositories"))
        {
        foreach (var requiredInterface in assemblyType.GetInterfaces())
        {
        if (requiredInterface.Namespace.EndsWith("Repositories"))
                 {
        var typeFrom = assemblyType.GetInterface(requiredInterface.Name);
        var typeTo = assemblyType;
        string registerName = String.Concat(baseName, "Repository");
        _container.RegisterType(typeFrom, typeTo, registerName);
                }
    }
    }

When resolving I get the exception:

Microsoft.Practices.Unity.ResolutionFailedException was unhandled by user code Message=Resolution of the dependency failed, type = "MyDll.Repositories.IRepository1[MyDll.Models.MyClass]", name = "MyDllRepository". Exception occurred while: while resolving. Exception is: InvalidOperationException - The current type, MyDll.Repositories.IRepository1[MyDll.Models.MyClass], is an interface and cannot be constructed.

Any Ideas?

MyDll.Repositories.Repository class:

    public class Repository<TModel> : IRepository<TModel> where TModel : class, IModel
{
    [Dependency("MyDllDataProvider")]
    public IMyDllDataProvider _dataProvider { get; set; }
    ...
}
1

1 Answers

0
votes

You basically want to register any implementation of your IRepository<> interface right?

There is a method in Unity 3.x for this kind of convention based registration. On the container you have a method RegisterTypes which takes different parameters for e.g. assemblies to scan, interfaces to look for etc...

So I assume that's exactly what you should do, and it works perfectly fine with generic types.

Just a quick example, which would scan all assemblies in the "bin" directory or whatever is your base path... and filters on the type name.

container.RegisterTypes(
   AllClasses.FromAssembliesInBasePath(), 
   (t) => t.Name.EndsWith("Service") ? new[] { t } : new Type[] { },
   WithName.TypeName);

You can totally customize each of the filters or instructions, those are just simple Func methods which can be customized easily.

After that you should be able to resolve them via e.g.

container.ResolveAll(typeof(IRepository<MyClass>));