IoC : using EntityFramework.Patterns with Unity 2.1


Given the following extremely simple model and context

    public class Workbench
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }

    public class Context : DbContext
    {

        public IDbSet<Workbench> Workbenches { get; set; }

        public Context()
        {
            Database.SetInitializer(new DropCreateDatabaseIfModelChanges<Context>());
        }
    }

that is intended to be used in the following Service

    public class Service
    {
        private readonly IRepository<Workbench> _repo;
        private readonly IUnitOfWork _uow;

        public Service(IRepository<Workbench> repo, IUnitOfWork uow)
        {
            _repo = repo;
            _uow = uow;
        }

        public IEnumerable<Workbench> LoadAll()
        {
            return _repo.GetAll();
        }

        public void Insert(Workbench workbench)
        {
            _repo.Insert(workbench);
            _uow.Commit();
        }
    }

We would like to inject the Repository and Unit of Work in the Service class.
We can achieve the injection like this :

public static class CompositionRoot
    {

        private static readonly IUnityContainer UnityContainer = new UnityContainer();

        public static IUnityContainer Container { get { return UnityContainer; } }

        public static void RegisterServices()
        {
            // Registering interfaces of Unit Of Work & Generic Repository
            UnityContainer.RegisterType(typeof(IRepository<>), typeof(Repository<>));
            UnityContainer.RegisterType(typeof(IUnitOfWork), typeof(UnitOfWork));

            // Every time we ask for a EF context, we'll pass our own Context.
            UnityContainer.RegisterType(typeof(DbContext), typeof(Context));

            // Tricky part.
            // Your repositories and unit of work must share the same DbContextAdapter, so we register an instance that will always be used
            // on subsequente resolve.
            // Note : you should not use ContainerControlledLifetimeManager when using ASP.NET or MVC
            // and use a per request lifetime manager
            UnityContainer.RegisterInstance(new DbContextAdapter(UnityContainer.Resolve<DbContext>()), new ContainerControlledLifetimeManager());

            UnityContainer.RegisterType<IObjectSetFactory>(
                new InjectionFactory(con => con.Resolve<DbContextAdapter>())
                );

            UnityContainer.RegisterType<IObjectContext>(
                new InjectionFactory(con => con.Resolve<DbContextAdapter>())
                );
        }
    }

From now on, we can use our repository like that :

class Program
    {
        static void Main(string[] args)
        {
            CompositionRoot.RegisterServices();

            Service s = CompositionRoot.Container.Resolve<Service>();
            
            IEnumerable<Workbench> lst = s.LoadAll();
            int cnt = lst.Count();

            s.Insert(new Workbench{Name = Guid.NewGuid().ToString()});

            lst = s.LoadAll();
            cnt = lst.Count();
        }
    }

Last edited Jan 28, 2012 at 11:14 PM by Fab_Michellonet, version 3

Comments

JAtkins Feb 28, 2013 at 5:27 AM 
This also appears to work for Ninject between the repository and UoW for MVC app. Not sure which is more correct, this or wndyd's comment.

kernel.Bind(typeof(IRepository<>)).To(typeof(Repository<>));
kernel.Bind(typeof(IUnitOfWork)).To(typeof(UnitOfWork));

kernel.Bind(typeof(DbContext)).To(typeof(YourDbContext));

//Repository and Unit of Work must chare the same DbContextAdapter
kernel.Bind<DbContextAdapter>().ToSelf().InRequestScope();

kernel.Bind<IObjectSetFactory>().ToMethod(c => kernel.Get<DbContextAdapter>());
kernel.Bind<IObjectContext>().ToMethod(c => kernel.Get<DbContextAdapter>());

wndyd Mar 5, 2012 at 8:07 AM 
//kernel.Load(Assembly.GetExecutingAssembly());
kernel.Bind(typeof(IRepository<>)).To(typeof(Repository<>));
// kernel.Bind(typeof(Repositories.IContentRepository)).To(typeof(Repositories.ContentRepository));
kernel.Bind(typeof(IUnitOfWork)).To(typeof(UnitOfWork));
kernel.Bind(typeof(DbContext)).To(typeof(YourDbContext));
//kernel.Bind<DbContextAdapter>().ToMethod(x => { return new DbContextAdapter(kernel.Get<DbContext>()); }).InRequestScope();
kernel.Bind<IObjectSetFactory>().ToMethod(c => { return kernel.Get<DbContextAdapter>(); });
kernel.Bind<IObjectContext>().ToMethod(c => { return kernel.Get<DbContextAdapter>(); });

fsy_008 Jan 29, 2012 at 2:37 PM 
修改怎么弄?