简体   繁体   中英

How to add DbSet<EntityName> to a context that is generated dynamically with Codedom?

I am generating entities dynamically using Codedom. I also don't have a hardcoded context class as part of the solution. That is, I am also generating the contexts at run time using Codedom. I am doing this so every generated entity has its own context. I am running into a problem with writing the Codedom code for the context class. As part of the context, I need to write in the DbSet property so the generated entity can be part of the model for the context. More specifically, I need the following line in my generated context:

public DbSet<EntityName> EntityNames { get; set; }

where EntityName is the name of the entity class type I have created, and EntityNames is just that name with an 's' on the end. For example, I might create an Employee entity, so I would like to generate a context with:

public DbSet<Employee> Employees { get; set; }

To do this I am writing a method that returns this CodeMemberProperty. It knows to write Employee/Employees because I pass in the name of the entity. That's fine. The method looks like this so far:

public static CodeMemberProperty HardCodeDbSet(string contextName)
{
    string entityName = contextName.Substring(0, contextName.Length - 7);
    CodeMemberProperty prop = new CodeMemberProperty();
    prop.Attributes = MemberAttributes.Public | MemberAttributes.Final;
    prop.Name = entityName + "s";
    prop.Type = new CodeTypeReference(typeof(DbSet<>));
    return prop;
}

The reason for this line:

string entityName = contextName.Substring(0, contextName.Length - 7);

is that I make the name of the generated context the corresponding entity name + "Context", so in that line I am removing "Context" to get back the entityName. Anyway, that's not really relevant. The line that's giving me trouble is the type one:

prop.Type = new CodeTypeReference(typeof(DbSet<>));

This just gives me:

DbSet<>

But I need:

DbSet<EntityName>

If I try to write anything inside the angle brackets I get an error saying that it can't resolve the symbol. For example I would like to write:

prob.Type = new CodeTypeReference(typeof(DbSet<entityType>));

And I could just make

Type entityType

a parameter of this method, but it doesn't like that.

Does anyone know a way around this? I thought it would be a lot simpler to code this, but Codedom isn't as cooperative as I thought sometimes...

What you're basically asking for here, if we go to the heart of the matter, is how to use reflection to get the Type of a closed generic type. This doesn't have anything to do with CodeDom or EntityFramework specifically.

As you mentioned, using typeof(DbSet<>) (or List<> , or anything) will give you the "open generic type", meaning the one that specific generic types are based on. From here, you can use the method MakeGenericType to create the specific closed generic type:

var openType = typeof(DbSet<>);
var closedType = openType.MakeGenericType(entityType);

您需要使用打开的通用DbSet<>并将其关闭,如下所示:

typeof(DbSet<>).MakeGenericType(entityType)

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