C# T必须是具有公共无参数构造函数的非抽象类型,才能将其用作参数';TModel';在泛型类型或方法中

C# T必须是具有公共无参数构造函数的非抽象类型,才能将其用作参数';TModel';在泛型类型或方法中,c#,asp.net-mvc,entity-framework,generics,abstract-class,C#,Asp.net Mvc,Entity Framework,Generics,Abstract Class,我尝试过搜索答案,但也遇到了类似的问题,但我无法用它们来解决我的问题,所以请尽量不要将其标记为重复。让我们进入真正的交易: 我有一个通用库,用于标准化实体框架数据库优先模型。 以下是我创建的泛型类: public abstract class GenericLookupModel : IActive, ICreated, IModified, IIdentity, IStringValue { public bool is_active { get; set; } public

我尝试过搜索答案,但也遇到了类似的问题,但我无法用它们来解决我的问题,所以请尽量不要将其标记为重复。让我们进入真正的交易:

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

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;
    }
}
以及一个用于具有预设MVC属性的ViewModel的类

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();
    }

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

public class RoleService : GenericLookupModelDataService<tblkp_Role, RoleViewModel> 
{

}
最后,让我们创建控制器:

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_角色类(DB优先方法):

使用系统;
使用System.Collections.Generic;
公共部分类tblkp_角色
{
[System.Diagnostics.CodeAnalysis.SuppressMessage(“Microsoft.Usage”,“CA2214:DoNotCallOverridableMethodsInConstructors”)]
公共tblkp_角色()
{
this.tbl_Employee=new HashSet();
}
公共int id{get;set;}
公共字符串值{get;set;}
公共字符串说明{get;set;}
公共布尔是活动的{get;set;}
在{get;set;}上创建了public System.DateTime
由{get;set;}创建的公共字符串
在{get;set;}上修改了public System.DateTime_
由{get;set;}修改的公共字符串
[System.Diagnostics.CodeAnalysis.SuppressMessage(“Microsoft.Usage”,“CA2227:CollectionPropertiesShouldBreadOnly”)]
公共虚拟ICollection tbl_Employee{get;set;}
}
更新2:纯文本格式的错误:

错误33“DataLayer.Model.tblkp_角色”必须是非抽象类型 使用公共无参数构造函数,以便将其用作 泛型类型或方法中的参数“TModel” 'MyLib.Model.GenericLookupModelDataService'c:\Projects\Sources\MyLib\bin\Release\MyLib.dll

错误32类型“DataLayer.Model.tblkp_Role”不能用作类型 泛型类型或方法中的参数“TModel” “MyLib.Model.GenericLookupModelDataService”。那里 没有从“DataLayer.Model.tblkp_角色”到 “MyLib.Model.GenericLookupModel”。c:\Projects\Sources\MyLib\bin\Release\MyLib.dll


您具有以下功能:

public abstract class GenericLookupModelDataService<TModel, TViewModel> : object 
    where TModel : GenericLookupModel, new()
    where TViewModel : GenericLookupViewModel, new()
{
  // ...
公共抽象类GenericLookupModelDataService:对象
其中TModel:GenericLookupModel,new()
其中TViewModel:GenericLookupViewModel,new()
{
// ...
该类有两个通用参数,分别称为
TModel
TViewModel
。每个参数都有约束,在
where
上下文关键字后指示

对于
TModel
,约束条件为:

  • 一种基类约束,要求类
    GenericLookupModel
    必须是替换
    TModel
    的任何类型的基类,以及
  • 构造函数约束
    new()
    要求用于
    TModel
    的类型必须公开一个接受零参数的
    public
    实例构造函数
您询问的错误之一是:

错误33“DataLayer.Model.tblkp_角色”必须是非抽象类型 使用公共无参数构造函数,以便将其用作 泛型类型或方法中的参数“TModel” 'MyLib.Model.GenericLookupModelDataService'

这仅仅意味着您尝试用于
TModel
的类型
tblkp\u Role
不符合构造函数约束。您有0参数构造函数吗

您询问的另一个错误是:

错误32类型“DataLayer.Model.tblkp_Role”不能用作 泛型类型或方法中的类型参数“TModel” “MyLib.Model.GenericLookupModelDataService”。在那里 没有从“DataLayer.Model.tblkp_角色”到 “MyLib.Model.GenericLookupModel”

这表示未满足基类约束。由于错误文本谈到“装箱转换”,因此编译器正在使用的类型
tblkp_Role
实际上是一种值类型(
struct
type,或
enum
type).像这样的类型永远不能根据约束要求从
GenericLookupModel
派生

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


在编译时错误的映像版本中,我们看到编译器还抱怨您使用的类型
tblkp_Role
是在没有引用的程序集中声明的。请尝试先修复该类型。如果编译器能够看到
tblkp_Role
的所有详细信息,其他类型可能会消失,因为它具有对定义该类型的项目的引用。

当您尝试在不同的类中使用相同的泛型类型参数,而不在其中至少一个类中定义所有约束时,通常会遇到您提到的错误。有关详细信息,请参阅Jon Skeet的回答

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

public abstract class GenericLookupModelDataService<TModel, TViewModel> : object 
    where TModel : GenericLookupModel, new()
    where TViewModel : GenericLookupViewModel, new()
{
  // ...
我在同一个代码文件中编写了所有代码,这意味着没有外部库。类似如下:

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()
    {

    }
}
类程序
{
静态void Main(字符串[]参数)
{
RoleService RoleService=新RoleService();
}
}
类RoleService:GenericLookupModelDataService
{ }
公共抽象类GenericLookupModelDataService:对象
其中TModel:GenericLookupModel,new()
其中TViewModel:GenericLookupViewModel,n
public abstract class GenericLookupModelDataService<TModel, TViewModel> : object 
    where TModel : GenericLookupModel, new()
    where TViewModel : GenericLookupViewModel, new()
{
  // ...
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()
    {

    }
}