首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >实体框架中的泛型添加方法--从字符串名称传入类型出错

实体框架中的泛型添加方法--从字符串名称传入类型出错
EN

Stack Overflow用户
提问于 2017-02-22 16:53:31
回答 2查看 134关注 0票数 0

我承认,我在这方面的问题很大程度上是因为对解决方案中涉及的几个组件缺乏理解。我并不完全是实体框架的“新手”,代码优先,也不是泛型类型,但这三种类型的内部工作方式对我来说仍然很神秘,这让我觉得很适合。

我有一个代码优先项目,在该项目中,我将“模型”类与“服务”类分离开来,并在这两种类中都进行了泛化。我是而不是,使用完整的存储库模式,原因有很多。对我所做的大部分工作来说,我所拥有的结构是非常完美的--我理解它,而且它看起来相当干净。

但是有一个方面我遇到了问题,那就是能够将我的模型类类型之一作为泛型参数传递给泛型服务对象的实例,给出模型类的字符串路径/名称。

(背景:我需要这样做,因为我在数据库中用JSON文件的初始化值“种子”了几个表。这个JSON文件包含模型实体的名称。因此,在运行时,我需要获取该字符串值,然后将其作为类型提供给执行数据库操作的泛型服务对象。)

下面是相关的代码片段:

BaseEntity.cs中,我具有顶级接口和许多抽象类,然后特定的模型实体继承这些类:

代码语言:javascript
复制
namespace POST.API.Models
{
    public interface IEntity
    {
        int Id { get; set; }
    }

    public abstract class BaseEntity { }

    public abstract class Entity : BaseEntity, IEntity
    {
        public virtual int Id { get; set; }
    }

    public abstract class TypeEntity : Entity
    {
        public TypeDefinition Definition { get; set; }
    }
}

BaseService.cs中,我有另一个接口和更抽象的类,特定的模型服务类可以从中继承。这里还有一个用于执行insert操作的具体类:

代码语言:javascript
复制
namespace POST.API.Services
{
    public interface IEntityService { }

    public abstract class BaseEntityService<T> : IEntityService
        where T : Models.BaseEntity
    {
        public T Fetch(int Id)
        {
            using (var Db = new PostDbContext())
            {
                return Db.Set<T>().Find(Id);
            }
        }

        public void Create(T Item)
        {
            if (Item != null)
            {
                using (var Db = new PostDbContext())
                {
                    DbSet Entity = Db.Set<T>();

                    Entity.Add(Item);
                    Db.SaveChanges();
                }
            }
        }

        public IEnumerable<T> All()
        {
            using (var Db = new PostDbContext())
            {
                return (IEnumerable<T>)Db.Set<T>().ToList();
            }
        }
    }

    public abstract class BaseTypeEntityService<T> : BaseEntityService<T>
        where T : Models.TypeEntity
    { }

    public abstract class BasePropertyTypeEntityService<T> : BaseTypeEntityService<T>
        where T : Models.PropertyTypeEntity { }

    public abstract class BasePropertyEntityService<T> : BaseEntityService<T>
        where T : Models.BaseEntity { }

    public class TypeEntityService<T> : BaseTypeEntityService<T>
        where T : Models.TypeEntity { }

    #endregion
}

我删除了一些与演示无关的方法。

我有一些代码,然后尝试使用这些基类遍历JSON文件并插入一些行,因此:

代码语言:javascript
复制
        using (PostDbContext Db = new PostDbContext())
        {
            string JsonString = System.IO.File.ReadAllText(JsonDataFile);
            DataSet JsonDataSet = JsonConvert.DeserializeObject<DataSet>(JsonString);
            foreach (DataTable Table in JsonDataSet.Tables)
            {
                Type EType = Type.GetType("POST.API.Models." + Table.TableName);
                POST.API.Models.BaseEntity E = (POST.API.Models.BaseEntity)Activator.CreateInstance(EType);
                Services.TypeEntityService<EType> S = new Services.TypeEntityService<EType>();

                foreach (DataRow Row in Table.Rows)
                {
                    // Set properties of E and call Create method of S
                }
            }
        }

我显然误解了一些基本的东西,因为这段代码不会编译。在这一行代码中:

代码语言:javascript
复制
Services.TypeEntityService<EType> S = new Services.TypeEntityService<EType>();

...I在我对EType的引用上得到一个错误,编译器抱怨“无法找到类型或名称空间‘EType’”

因此,很明显,那里的引用不能在运行时进行计算。这让我想知道我到底是怎么做到的。所有相关的话题似乎都无法给出令人满意的答案--至少在我自己的实施过程中,这样做是不合理的。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-02-22 17:07:45

您需要使用Activator创建Services.TypeEntityService<EType>,如下所示.

代码语言:javascript
复制
            Type EType = Type.GetType("POST.API.Models." + Table.TableName);
            Type[] typeArgs = { EType };
            var generic = typeof(Services.TypeEntityService<>).MakeGenericType(typeArgs);
            var S = Activator.CreateInstance(generic);
票数 1
EN

Stack Overflow用户

发布于 2017-02-22 17:08:22

嗯,在EType中有一个System.Type类型的变量。不能将Type实例用于泛型类型。您应该将Services.TypeEntityService的实现更改为采用运行时类型实例(例如TypeEntityService(System.Type类型))。

编辑:或者实际上和其他回答状态一样,使用反射从Type实例构建泛型参数。这更有道理。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42397625

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档