简体   繁体   中英

Prevent Instantation of class outside of this class

I use Entity Framework and the generated classes for the DbContext . This classes are generated and every change I do is overwritten the next time I refresh my DbContext .

Now I override this class to generate the connection to the database dynamically, which works well. But the problem is, that you can create the class with the parameterless constructor as well and this leads to big problems if the connection is not dynamic.
Is there any way to forbid the instantion of the generated class with the parameterless constructor outside of the generated class?

For example:
The generated class without parameter:

public partial class SomeConnection : DbContext
{
    public SomeConnection()
        : base("name=myWrongConnection")
    {
       //should not be able to be called!
    }

    // some more generated and needed stuff!
    ...
}

And here the class I need to instantiate:

public partial class SomeConnection
{
    public SomeConnection(String connectionString)
        : base(connectionString)
    {
        // only this constructor should be called without changing the parent class...
    }
}

It's better to use a factory, but if you absolutely need to prohibit using a wrong instance, a possible workaround would be overriding OnModelCreating , so the instance could not be used, even if created with a wrong constructor:

public partial class SomeConnection
{
  private readonly bool correctConstructorWasCalled;

  public DerivedContext(string connectionString)
            :base(connectionString)
  {
      correctConstructorWasCalled = true;
  }

  protected override void OnModelCreating(DbModelBuilder modelBuilder)
  {
    if (!correctConstructorWasCalled)
    {
        throw new InvalidOperationException("Please call the correct constructor.");
    }
    base.OnModelCreating(modelBuilder);
  }
}

UPDATE:

I have found a solution to absolutely deny a specific constructor:

public class Guard
{
  public Guard([CallerMemberName] string callerName = null)
  {
    var constructorExpression = (Expression<Func<Prohibited>>)(() => new Prohibited());
    var constructorMethod = (NewExpression) (constructorExpression.Body);

    var stackFrames = new StackTrace().GetFrames();
    if (stackFrames.Any(f => f.GetMethod() == constructorMethod.Constructor))
    {
      throw new InvalidOperationException("Aha! you are still trying.");
    }
  }
}

public partial class Prohibited : DbContext
{
   public Prohibited()
            : base("wrong connection string")
   {
   }
}

public partial class Prohibited 
{
  private Guard guard = new Guard();

  public Prohibited(string connectionString)
            : base(connectionString)
  {
  }
}

[CallerMemberName] is needed so the caller frame is not optimized out in Release configurations.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM