简体   繁体   中英

How to correctly setup custom constructors using Codedom

I am trying to get Codedom to generate the following code:

public class NewContext : DbContext
{

    public NewContext()
        : base("NewContext")
    {
        EntityToRegisterDictionary = new ConcurrentDictionary<string, Assembly>();
    }

    static NewContext()
    {
        Database.SetInitializer(new DropCreateDatabaseIfModelChanges<EFEntityModelContext>());
    }
}

I can generate

public class NewContext : DbContext

without any problems. I'm running into problems with writing the code that creates the two constructors. I have created two methods, one method for each constructor. This is what my methods look like:

public static CodeConstructor BaseStringConstructor(string connectionStr)
{
    CodeConstructor baseStringConstructor = new CodeConstructor();
    baseStringConstructor.Attributes = MemberAttributes.Public;
    baseStringConstructor.BaseConstructorArgs.Add(new CodeVariableReferenceExpression("\"connectionStr\""));
    CodeAssignStatement body = new CodeAssignStatement();
    body.Left = new CodeFieldReferenceExpression(new CodeFieldReferenceExpression(), "EntityToRegisterDictionary");
    body.Right = new CodeObjectCreateExpression("ConcurrentDictionary<string, Assembly>");
    baseStringConstructor.Statements.Add(body);
    return baseStringConstructor;
}

public static CodeConstructor StaticInitializerConstructor()
{
    CodeConstructor constructor = new CodeConstructor();
    constructor.Attributes = MemberAttributes.Static;
    CodeObjectCreateExpression body = new CodeObjectCreateExpression("Database.SetInitializer(new DropCreateDatabaseIfModelChanges<EFEntityModelContext>");            
    constructor.Statements.Add(body);
    return constructor;
}

This code doesn't produce exactly the code I want above, however. I get:

public NewContext() : 
        base("connectionStr")
{
    .EntityToRegisterDictionary = new ConcurrentDictionary<string, Assembly>();
}

NewContext()
{
    new Database.SetInitializer(new DropCreateDatabaseIfModelChanges<EFEntityModelContext>();
}

The problem in the "public NewContext()" constructor is that there is a '.' before

EntityToRegisterDictionary

I assume this is because of the line

body.Left = new CodeFieldReferenceExpression(new CodeFieldReferenceExpression(), "EntityToRegisterDictionary");

Does anyone know how to make it without the period?

There are three problems with the "static NewContext()" constructor:

  1. Codedom doesn't write static before NewContext()

  2. It writes new before Database.

  3. I can't add a right parenthesis after the () at the end because () is added automatically after whatever I write.

Does anyone know how to just make it write

Database.SetInitializer(new DropCreateDatabaseIfModelChanges<EFEntityModelContext>());

without the new keyword and with the addition right parenthesis?

Edit: By the way, EntityToRegisterDictionary is something I define below as:

public IDictionary<string, Assembly> EntityToRegisterDictionary { get; private set; }

I just haven't included all of this context class.

The problem in the "public NewContext()" constructor is that there is a '.' before

Yes, you are providing a CodeFieldReferenceExpression with no actual field reference so it's just using an empty string. What you're looking for is CodeThisReferenceExpression since you're just accessing a member on the same class.

body.Left = new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), "EntityToRegisterDictionary");

This will generate the assignment using the this keyword as shown below:

this.EntityToRegisterDictionary = new ConcurrentDictionary<string, Assembly>();

Codedom doesn't write static before NewContext()

You are using CodeConstructor which creates an instance constructor. The fact that one of the attributes you can provide is MemberAttributes.Static is a little misleading, but it becomes clear when you read the remarks section of the documentation . You should be using CodeTypeConstructor to generate a static constructor.


It writes new before Database. I can't add a right parenthesis after the () at the end because () is added automatically after whatever I write.

You are using CodeObjectCreateExpression , which is used to create a new instance of a type, to try and call a static method. To call a method, you would use CodeMethodInvokeExpression . You should first create an expression for the Database.SetInitializer method and pass the argument using CodeObjectCreateExpression .

var method = new CodeMethodReferenceExpression(new CodeTypeReferenceExpression("Database"), "SetInitializer");
var body = new CodeMethodInvokeExpression(method, new CodeObjectCreateExpression("DropCreateDatabaseIfModelChanges<EFEntityModelContext>"));
constructor.Statements.Add(body);
CodeAssignStatement body = new CodeAssignStatement();
body.Left = new CodeFieldReferenceExpression(null, "Propiedad ");
body.Right = new CodeFieldReferenceExpression(null, "parametro");

------------------------------- OUTPUT--------------------------------
private Metodo(string parametro) {
    Propiedad = parametro;
}

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