Constructor argument on lifestyle registration

Oct 2, 2014 at 3:44 PM
Edited Oct 2, 2014 at 3:45 PM
I am fiddling a bit around with some lifestyle registration, but I need to supply a constructor argument to this registration, is this possible or am I doing this wrong?
public static void RegisterEntityFramework(this Container container, ScopedLifestyle lifestyle, string connectionString)
{
    var contextRegistration = lifestyle.CreateRegistration<MyCustomDbContext, MyCustomDbContext>(container);
    container.AddRegistration(typeof(DbContext), contextRegistration);
    container.AddRegistration(typeof(MyCustomDbContext), contextRegistration);
    container.AddRegistration(typeof(IUnitOfWork), contextRegistration);
    container.AddRegistration(typeof(IWriteEntities), contextRegistration);
    container.AddRegistration(typeof(IReadEntities), contextRegistration);

    container.Register(() => new MyCustomDbContext(connectionString), lifestyle); // double registration?
}
Invoked with
container.RegisterEntityFramework(new WebRequestLifestyle(), "MyConnectionStringGoesHere");
Oct 2, 2014 at 3:51 PM
Just browsed StackOverflow, maybe this is the way?
container.Register(() => new NerveDbContext(connectionString), lifestyle);
container.Register<DbContext>(container.GetInstance<NerveDbContext>);
container.Register<IUnitOfWork>(container.GetInstance<NerveDbContext>);
container.Register<IWriteEntities>(container.GetInstance<NerveDbContext>);
container.Register<IReadEntities>(container.GetInstance<NerveDbContext>);
Coordinator
Oct 2, 2014 at 5:40 PM
What are you trying to achieve?
Oct 2, 2014 at 5:53 PM
Registering all my interfaces to the NerveDbContext, with a specific lifestyle and a constructor argument for the connectionstring. Am I making any sense?
Coordinator
Oct 2, 2014 at 7:13 PM
Edited Oct 2, 2014 at 8:34 PM
Hi @meepdk,

Your solution from StackOverflow looks to me like it would work but it's not the most efficient way to use the container.

I would advise you to define a simple abstraction to provide the connections strings
public interface IConnectionStrings
{
    string NerveDbConnection { get; }
}

public class NerveDbContext
{
    private readonly string connectionString;

    public NerveDbContext(IConnectionStrings connectionStrings)
    {
        this.connectionString = connectionStrings.NerveDbConnection;
    }
}

private class ConnectionStrings : IConnectionStrings
{
    public ConnectionStrings(string nerveDbConnection)
    {
        this.NerveDbConnection = nerveDbConnection;
    }

    public string NerveDbConnection { get; private set; }
}

container.RegisterSingle<IConnectionStrings>(new ConnectionStrings("<details>"));

Coordinator
Oct 2, 2014 at 10:46 PM
In my opinion, the following would be the most convenient:
public static void RegisterEntityFramework(this Container container, ScopedLifestyle lifestyle, 
    string connectionString)
{
    var contextRegistration = lifestyle.CreateRegistration<MyCustomDbContext>(
        () => new MyCustomDbContext(connectionString), container);

    container.AddRegistration(typeof(DbContext), contextRegistration);
    container.AddRegistration(typeof(MyCustomDbContext), contextRegistration);
    container.AddRegistration(typeof(IUnitOfWork), contextRegistration);
    container.AddRegistration(typeof(IWriteEntities), contextRegistration);
    container.AddRegistration(typeof(IReadEntities), contextRegistration);
}
I think this is what you're trying to achieve: within a single scope, there is just one instance of MyCustomDbContext and it can be resolved and injected as DbContext, MyCustomDbContext, IUnitOfWork, IWriteEntities and IReadEntities.
Marked as answer by dot_NET_Junkie on 11/3/2014 at 1:25 AM
Oct 3, 2014 at 5:30 AM
Exactly, I was not aware of that overload. Must have missed it - thanks a lot! :-)