Search code examples
c#.netactivator

Activator.CreateInstance with param - constructor of child class type not found


I try to pass connectionString to context factory constructor, but got a error "constructor type of ContextImplementationTest not found" What is the problem? I'm calling

string bid="someCOnnectionString";
using (BaseContext<DbContext> db = MediaDbContext.GetBidContext(bid)){...}


public static class MediaDbContext
{
   public static BaseContext<DbContext> GetBidContext(string connString)
    {
        //Settings.ContextFactory="ContextImplementationTest"
        Type contextFactoryType = Type.GetType("Media.DB.Context.Implementation." + Settings.ContextFactory);
        object[] args = new object[] { connString};
        BaseContext<DbContext> instance = (BaseContext<DbContext>)Activator.CreateInstance(contextFactoryType, args);
        return instance;
    }
}

Base Class

public class BaseContext<TContext> : DbContext where TContext : DbContext
{
    static BaseContext()
    {
        Database.SetInitializer<TContext>(null);
    }

    protected BaseContext(string connectionString) : base(connectionString)
    {
    }...

Child class

public class ContextImplementationTest : BaseContext<DbContext>
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {...}

Update: to call constructor in child class, you need to have constructor in this class.

Child class

public class ContextImplementationTest : BaseContext<DbContext>
{
   protected ContextImplementationTest(string connectionString) : base(connectionString)
   {
   }...

Solution

  • Activator.CreateInstance takes a nonPublic parameter only in the case of default constructor invocation.

    You can use Type.GetConstructor instead:

    Type contextFactoryType = 
        Type.GetType("Media.DB.Context.Implementation." + Settings.ContextFactory);
    
    ConstructorInfo ci = contextFactoryType .GetConstructor(
        BindingFlags.Instance | BindingFlags.NonPublic,
        binder: null, new Type[] { typeof(string) }, modifiers: null);
    
    object[] args = new object[] { connString };
    
    var instance = (BaseContext<DbContext> instance)ci.Invoke(args);
    return instance;