Multiple constructors and using ctor does not inject right one

Jul 11, 2012 at 9:18 AM
Edited Jul 11, 2012 at 10:06 AM

Hey, okay running in to a problem with constructor resolution...

I have this class...

 

    public class SusDataContext : DbContext, ISusDataContext
    {
        public SusDataContext()
            : this(ConfigurationManager.ConnectionStrings["SusDataContext"].ConnectionString)
        {

        }

        public SusDataContext(string connectionString)
            : this(connectionString, new SusDataContextInitializer())
        {
            
        }

        public SusDataContext(string connectionString, IDatabaseInitializer<SusDataContext> databaseInitiliser)
            : base(connectionString)
        {
            ((IObjectContextAdapter)this).ObjectContext.CommandTimeout = 3000;
            Database.SetInitializer(databaseInitiliser);
        }

 

And I want to call only the second ctor from unity... So I do this...

 

            builder.For<IDbContext>().Use<SusDataContext>().Named("SusDataContext").LifetimeIs(new HierarchicalLifetimeManager())
                .Ctor(x => x.With(ConfigurationManager.ConnectionStrings["SusDataContext"].ToString()));
            builder.For<ISusDataContext>().Use<SusDataContext>().Named("SusDataContext").LifetimeIs(new HierarchicalLifetimeManager())
                .Ctor(x => x.With(ConfigurationManager.ConnectionStrings["SusDataContext"].ToString()));

 

I previously did this, which is not thread safe

 

            container.RegisterType<IDbContext, SusDataContext>("SusDataContext",
                new HierarchicalLifetimeManager(), new InjectionConstructor(ConfigurationManager.ConnectionStrings["SusDataContext"].ToString()));
            container.RegisterType<ISusDataContext, SusDataContext>("SusDataContext",
                new HierarchicalLifetimeManager(), new InjectionConstructor(ConfigurationManager.ConnectionStrings["SusDataContext"].ToString()));

 

The problem is that the third constructor is the one that always gets called not the second one... Any ideas what I am doing wrong?

Cheers, Nick

Coordinator
Jul 11, 2012 at 10:14 AM

The overload of the Ctor() method you are using configures a ClozeInjectionConstructor. This one looks for the ctor with the most parameters it can possibly satisfy. IDatabaseInitializer is not a primitive type so it takes it for granted that the container is used to resolve that type.

I added another overload Ctor(params object[] parameterValues) that lets you specify exactly which ctor you want to use.

Jul 11, 2012 at 2:29 PM
Edited Jul 11, 2012 at 3:02 PM

Fantastic, that works thanks :) , what would the constructor be in TecX for

 

container.RegisterType<IRepository<DataConstant>, EFRepository<DataConstant>>(
       new InjectionConstructor(new ResolvedParameter(typeof(IDbContext), "RtmDataContext"))
);

Ive tried this but it doesnt work...

builder.For<IRepository<DataConstant>>().Use<EFRepository<DataConstant>>()
	.Ctor((x) => x.With(new ResolvedParameter(typeof (IDbContext), "RtmDataContext")));

Cheers, Nick

Coordinator
Jul 11, 2012 at 3:45 PM

Does your EFRepository have more than one constructor and you don't want to use the one with the most parameters? Then the solution looks like the one before:

builder.For<IRepository<DataConstants>>().Use<EFRepository<DataConstant>>().Ctor(new ResolvedParameter(typeof(IDbContext), "RtmDataContext")));