繁体   English   中英

T必须是具有公共无参数构造函数的非抽象类型,以便在泛型类型或方法中将其用作参数“TModel”

[英]T must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'TModel' in the generic type or method

我已经尝试搜索SO以获得答案并偶然发现类似的问题,但我无法使用它们来解决我的问题,所以请尽量不要将其标记为重复。 让我们继续谈谈真正的交易:

我有一个通用库,用于标准化实体框架数据库的第一个模型。 这些是我创建的泛型类:

public abstract class GenericLookupModel : IActive, ICreated, IModified, IIdentity, IStringValue
{
    public bool is_active { get; set; }
    public string value { get; set; }
    public string description { get; set; }
    public DateTime created_on { get; set; }
    public string created_by { get; set; }
    public DateTime modified_on { get; set; }
    public string modified_by { get; set; }
    public int id {get;set;}

    public void SetCreated(string creator = "SYSTEM")
    {
        created_by = creator;
        created_on = DateTime.Now;
    }

    public void SetModified(string modifier = "SYSTEM")
    {
        modified_by = modifier;
        modified_on = DateTime.Now;
    }
}

并且ViewModel的类具有预先设置的MVC属性

public abstract class GenericLookupViewModel
{
    [Key]
    public int ID { get; set; }

    [Required]
    [StringLength(300)]
    public string Name { get; set; }

    [StringLength(4000)]
    public string Description { get; set; }

    [Required]
    public bool Active { get; set; }

    [StringLength(50)]
    [DisplayName("Record last modified by")]
    public string ModifiedBy { get; set; }

    [DisplayName("Record last modified Date")]
    [DataType(DataType.Date)]
    [DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}", ApplyFormatInEditMode = true)]
    public DateTime ModifiedOn { get; set; }

    [StringLength(50)]
    [DisplayName("Record created by")]
    public string CreatedBy { get; set; }

    [DisplayName("Record creation Date")]
    [DataType(DataType.Date)]
    [DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}", ApplyFormatInEditMode = true)]
    public DateTime CreatedOn { get; set; }
}

另外,我已经创建了一个服务类,我打算在控制器中使用它来获取数据:

public abstract class GenericLookupModelDataService<TModel, TViewModel> : object 
    where TModel : GenericLookupModel, new()
    where TViewModel : GenericLookupViewModel, new()
{
    private readonly DbContext _db;

    private DbContext entities
    {
        get { return _db; }
    }

    public GenericLookupModelDataService()
    {
        _db =
            new DbContext(
                System.Configuration.ConfigurationManager.ConnectionStrings["DefaultConnectionString"].ConnectionString);
    }

    public virtual IEnumerable<TViewModel> ReadAllActive()
    {
        return entities.Set<TModel>().Where(x => x.is_active).Select(product => new TViewModel
        {
            ID = product.id,
            Active = product.is_active,
            Description = product.description,
            Name = product.value,
            CreatedBy = product.created_by,
            CreatedOn = product.created_on,
            ModifiedBy = product.modified_by,
            ModifiedOn = product.modified_on
        });
    }

    public virtual IEnumerable<TViewModel> Read()
    {
        return entities.Set<TModel>().Select(product => new TViewModel
        {
            ID = product.id,
            Active = product.is_active,
            Description = product.description,
            Name = product.value,
            CreatedBy = product.created_by,
            CreatedOn = product.created_on,
            ModifiedBy = product.modified_by,
            ModifiedOn = product.modified_on
        });
    }

    public virtual void Create(TViewModel product, string username = "SYSTEM")
    {
        var entity = new TModel
        {
            is_active = product.Active,
            description = product.Description,
            value = product.Name,
        };

        entity.SetCreated();
        entity.SetModified();

        _db.Set<TModel>().Add(entity);
        _db.SaveChanges();
    }

    public virtual void Update(TViewModel product, string username = "SYSTEM")
    {
        var entity = new TModel
        {
            id = product.ID,
            is_active = product.Active,
            description = product.Description,
            value = product.Name
        };
        entity.SetModified();


        _db.Set<TModel>().Attach(entity);
        entities.Entry(entity).State = EntityState.Modified;
        entities.SaveChanges();
    }

    public virtual void Destroy(TViewModel product)
    {
        var entity = new TModel {id = product.ID};

        entities.Set<TModel>().Attach(entity);
        entities.Set<TModel>().Remove(entity);
        entities.SaveChanges();
    }

    public virtual TViewModel GetByID(int ID)
    {
        var item = entities.Set<TModel>().Find(ID);
        var result = new TViewModel
        {
            ID = item.id,
            Active = item.is_active,
            CreatedBy = item.created_by,
            CreatedOn = item.created_on,
            Description = item.description,
            ModifiedBy = item.modified_by,
            ModifiedOn = item.modified_on,
            Name = item.value
        };
        return result;
    }

    public void Dispose()
    {
        entities.Dispose();
    }

}

库编译得很好,我在我的MVC App里面的数据层项目中使用它。 首先创建一个新的视图模型:

public class RoleViewModel : GenericLookupViewModel
{


}

然后,让我们创建一个服务:

public class RoleService : GenericLookupModelDataService<tblkp_Role, RoleViewModel> 
{

}

使Entity Framework类继承自抽象模型:

partial class tblkp_Role : GenericLookupModel
{

}

最后让我们创建我们的控制器:

public class EmployeeController : Controller
{
    private RoleService roleService;

    public EmployeeController()
    {
        dataService = new EmployeeService();
        PopulateLookups();
    }

    private void PopulateLookups()
    {
        roleService = new RoleService();
        ViewData["roles"] = roleService.ReadAllActive();
    }

    public ActionResult Index()
    {
        return View();
    }

}

对于代码墙感到抱歉,为简洁起见,已删除了一些代码。 编译它时给了我3个错误: 在此输入图像描述

更新 :提供由EF自动生成的tblk_Role类(DB First方法):

using System;
using System.Collections.Generic;

public partial class tblkp_Role
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public tblkp_Role()
    {
        this.tbl_Employee = new HashSet<tbl_Employee>();
    }

    public int id { get; set; }
    public string value { get; set; }
    public string desciption { get; set; }
    public bool is_active { get; set; }
    public System.DateTime created_on { get; set; }
    public string created_by { get; set; }
    public System.DateTime modified_on { get; set; }
    public string modified_by { get; set; }

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<tbl_Employee> tbl_Employee { get; set; }
}

更新2 :纯文本格式的Erros:

错误33'DataLayer.Model.tblkp_Role'必须是具有公共无参数构造函数的非抽象类型,以便在泛型类型或方法'MyLib.Model.GenericLookupModelDataService <TModel,TViewModel>'c中将其用作参数'TModel' :\\项目\\来源\\ MyLib中\\ BIN \\发布\\中是指mylib.dll

错误32类型'DataLayer.Model.tblkp_Role'不能用作泛型类型或方法'MyLib.Model.GenericLookupModelDataService <TModel,TViewModel>'中的类型参数'TModel'。 没有从'DataLayer.Model.tblkp_Role'到'MyLib.Model.GenericLookupModel'的装箱转换。 C:\\项目\\来源\\ MyLib中\\ BIN \\发布\\中是指mylib.dll

你有以下几点:

public abstract class GenericLookupModelDataService<TModel, TViewModel> : object 
    where TModel : GenericLookupModel, new()
    where TViewModel : GenericLookupViewModel, new()
{
  // ...

该类有两个名为TModelTViewModel通用参数。 其中每个都有对它的约束 ,在where contextual关键字后面指出。

对于TModel ,约束是:

  • 一个基类约束,要求类GenericLookupModel必须是TModel替换的类型的基类,并且
  • 构造函数约束new()要求用于TModel的类型必须公开一个接受零参数的public实例构造函数。

你问的一个错误是:

错误33'DataLayer.Model.tblkp_Role'必须是具有公共无参数构造函数的非抽象类型,才能在泛型类型或方法'MyLib.Model.GenericLookupModelDataService <TModel,TViewModel>'中将其用作参数'TModel'

这只是意味着您尝试用于TModel的类型tblkp_Role不符合构造函数约束。 你有0参数构造函数吗?

您询问的另一个错误是:

错误32类型'DataLayer.Model.tblkp_Role'不能用作泛型类型或方法'MyLib.Model.GenericLookupModelDataService <TModel,TViewModel>'中的类型参数'TModel'。 没有从'DataLayer.Model.tblkp_Role'到'MyLib.Model.GenericLookupModel'的装箱转换。

这表示不满足基类约束。 由于错误文本讨论了“装箱转换”,因此看起来编译器正在使用的类型tblkp_Role实际上是值类型( struct类型或enum类型)。 类似的类型永远不能从约束所需的GenericLookupModel派生。

必须是C#编译器使用的类型tblkp_Role ,是使用partial class tblkp_Role : GenericLookupModel定义的类型的另一种类型partial class tblkp_Role : GenericLookupModel 您可能在引用的项目中有一些冲突的名称或一些重复的代码/名称。

在编译时错误的映像版本中,我们看到编译器还抱怨您使用的类型tblkp_Role是在您没有引用的程序tblkp_Role声明的。 先尝试修复那个。 一旦编译器可以看到tblkp_Role所有细节,其他的将会消失,因为它具有对定义该类型的项目的引用。

当您尝试在不同的类中使用相同的泛型类型参数而不在其中至少一个中定义所有约束时,通常会遇到您提到的错误。 请参见乔恩斯基特对清晰的答案。

但是你只在一个类中使用TModel,即GenericLookupModelDataService,因此我尝试了以下方法:

我在同一个代码文件中编写了所有代码,这意味着没有外部库。 像这样的东西:

class Program
{
    static void Main(string[] args)
    {
        RoleService roleService = new RoleService();
    }
}

class RoleService : GenericLookupModelDataService<tblkp_Role, RoleViewModel> 
{ }

public abstract class GenericLookupModelDataService<TModel, TViewModel> : object
    where TModel : GenericLookupModel, new()
    where TViewModel : GenericLookupViewModel, new()
{ }

public abstract class GenericLookupViewModel { }

public abstract class GenericLookupModel { }

public class RoleViewModel : GenericLookupViewModel { }

public partial class tblkp_Role : GenericLookupModel 
{
}

public partial class tblkp_Role
{
    public tblkp_Role()
    {

    }
}

这成功编译。 因此我怀疑编译器不知道tblkp_Role的完整定义。

我建议重新构建库并再次重新引用它(同时检查引用路径以确保您没有错误地引用旧版本)。

我遇到了部分类的类似问题,这些问题是由我在数据库第一种方法中自动创建的,当我尝试定义元数据类时。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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