T muss ein nicht abstrakter Typ mit einem öffentlichen parameterlosen Konstruktor, um es zu verwenden als parameter 'TModel' im generischen Typ oder Methode
Ich habe versucht, auf der Suche SO für die Antwort und stolperte über ähnliche Probleme, aber ich konnte das nicht gelingt, verwenden Sie für die Lösung meines Problems ist, also bitte versuchen Sie nicht, markieren Sie diese als Duplikat. Let ' s move on, um den real deal:
Habe ich eine generische Bibliothek für die Standardisierung entity framework-database first-Modelle.
Diese sind generische Klassen, die ich erstellt habe:
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;
}
}
Und eine Klasse für das ViewModel mit pre-set-MVC-Parametern
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; }
}
Außerdem habe ich eine service-Klasse, die ich beabsichtige zu verwenden, in der Steuerung für das abrufen von Daten:
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();
}
}
Der Bibliothek kompiliert in Ordnung, ich benutze es in der Daten-Ebene Projekt-in meinem MVC-App. Beginnen Sie, indem Sie eine neue Ansicht Modell:
public class RoleViewModel : GenericLookupViewModel
{
}
Dann können einen Dienst erstellen:
public class RoleService : GenericLookupModelDataService<tblkp_Role, RoleViewModel>
{
}
Stellen Sie die Entity Framework-Klassen Erben von der abstrakten Modells:
partial class tblkp_Role : GenericLookupModel
{
}
Schließlich wollen wir unsere controller:
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();
}
}
Sorry für die wall-of-code -, code ist bereits aus Gründen der Kürze entfernt.
Beim kompilieren gibt er mir 3 Fehler:
UPDATE: Vorausgesetzt tblk_Role Klasse automatisch generiert durch EF (DB-First-Ansatz):
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; }
}
UPDATE 2: Fehler im nur-text-format:
Fehler 33 'DataLayer.Modell.tblkp_Role' must be a non-abstract Art
mit einem öffentlichen parameterlosen Konstruktor, um es zu verwenden als
parameter 'TModel' im generischen Typ oder Methode
'MyLib.Modell.GenericLookupModelDataService<TModel,TViewModel>' c:\Projects\Sources\MyLib\bin\Release\MyLib.dllFehler 32 Der Typ 'DataLayer.Modell.tblkp_Role' kann nicht als Typ
parameter 'TModel' im generischen Typ oder Methode
'MyLib.Modell.GenericLookupModelDataService<TModel,TViewModel>'. Es
ist keine boxing-Konvertierung von 'DataLayer.Modell.tblkp_Role' zu
'MyLib.Modell.GenericLookupModel'. c:\Projects\Sources\MyLib\bin\Release\MyLib.dll
- Einer Ihrer Fehler sagt, müssen Sie einen Verweis hinzufügen. Haben Sie das getan?
- Das zu erklären: In Ihrem controller, den Sie verwenden, die
RoleService
, die direkt erbt vonGenericLookupModelDataService<tblkp_Role, RoleViewModel>
. Eine Konsequenz dieser Konstruktion ist, dass jede andere Klasse verwendet dieRoleService
(zum Beispiel IhreEmployeeController
) muss auch eine direkte Kenntnis der alles direkt ausgesetzt in der vererbungsstruktur. So, auchtblkp_Role
muss bekannt sein, durch Ihre controller. - Ja, habe ich. Library-Referenz existiert in allen 3 Projekten, in meiner Lösung. Scheint der controller nicht irgendwelche Probleme haben, zu wissen, tblkp_Role
- Sie zeigen nur eine partielle definition der
tblkp_Role
. Ist es nicht Abstrakt? Hat es einen öffentlichen parameterlosen Konstruktor? - Ja, es ist nicht Abstrakt und hat einen öffentlichen parameterlosen Konstruktor, in der Tat. Es generierte Entity Framework-Database First Ansatz. Ich habe es in den code.
- Bitte copy/paste Fehler als text anstatt als Bilder posten (das ist nicht sehr freundlich für Menschen mit kleinen Bildschirmen oder sehbehindert sind, etc.). Vielen Dank.
- Aktualisiert die post mit, dass die kosmetische Korrektur. Es ist in UPDATE 2
- Der Dritte Fehler, können Sie auf die benötigte Baugruppe ersten? Möglicherweise müssen Sie zum referenzieren der aktuellen EF-Paket auch.
- Sind die partiellen Klassen definiert, die in verschiedenen Baugruppen?
- partielle Klassen werden in der gleichen Versammlung: "Alle partiellen Typdefinitionen, die gedacht werden, um Teile des gleichen Typs definiert werden muss, in der gleichen assembly und dem gleichen Modul (.exe-oder .dll-Datei). Partielle Definitionen können sich über mehrere Module." - von MSDN.
- Ich weiß, ich dachte, dass je nach den Referenzen, wenn nur eine partielle Klasse sichtbar ist, dann könnte es erklären, ein Zustand (sagen, wenn nur die EF-erzeugt ein sichtbar war, es würde brechen die Einschränkung auf den service). Nun ich glaube nicht, dass es sein würde, diesen Fehler obwohl, Jeppe ist wahrscheinlich Recht mit seiner Antwort -- etwas fehlen, ist die Frage, oder aber es ist etwas, das ziemlich überraschend ist.
- ist es möglich, erstellen Sie eine Klasse, die Sie erweitert tblkp_Role und verwenden Sie diese neue Klasse statt?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Haben Sie die folgenden:
Diese Klasse hat zwei generische Parameter aufgerufen
TModel
undTViewModel
. Jeder von Ihnen hat Einschränkungen, um es angezeigt, nachdem daswhere
kontextbezogene Schlüsselwort.Für
TModel
Einschränkungen:GenericLookupModel
muss eine Basis-Klasse, von was auch immer geben wird ersetzt fürTModel
, undnew()
erfordern, dass der Typ, mitTModel
Belichten muss einpublic
Instanz-Konstruktor, null Argumente.Einer der Fehler, die Sie Fragen, ist:
Bedeutet dies einfach, dass der Typ
tblkp_Role
die Sie versuchen zu verwenden, fürTModel
entspricht nicht den Konstruktor Einschränkung. Sie haben die 0-parameter-Konstruktor?Anderen Fehler, den Sie Fragen, ist:
Dies bedeutet, dass die Basisklasse constraint nicht erfüllt ist. Da der Fehler text spricht über "boxing-Konvertierung", es scheint, dass die Art
tblkp_Role
die der compiler nutzt, ist in der Tat ein Wert-Typ (struct
geben, oderenum
- Typ). Typen wie diese kann nie ableiten ausGenericLookupModel
wie die Einschränkung erfordert.Muss es sein, dass der Typ
tblkp_Role
dass der C# - compiler verwendet, ist ein anderer Typ als der Typ, den Sie definieren mitpartial class tblkp_Role : GenericLookupModel
. Sie müssen möglicherweise einige widersprüchliche Namen oder einige doppelte code/Namen von referenzierten Projekten.In der Bild-version Ihres compile-Zeit Fehler, die wir sehen, dass der compiler sich beschwert, dass der Typ
tblkp_Role
dem Sie deklariert ist, in einer assembly, die Sie haben, keine Erwähnung. Befestigung versuchen, dass zuerst. Vielleicht die anderen gehen Weg, sobald der compiler alle details dertblkp_Role
weil es den Bezug zum Projekt definiert Art.Den Fehler, den Sie erwähnt haben, ist in der Regel konfrontiert, wenn Sie versuchen, verwenden die gleiche generische Typ-parameter in verschiedenen Kategorien ohne Definition aller Randbedingungen, die in mindestens einer von Ihnen. Sehen diese Jon Skeet Antwort für Klarheit.
Aber Sie sind mit Tmodels nur in einer Klasse, hier also GenericLookupModelDataService, also ich habe Folgendes versucht:
Schrieb ich den gesamten code in der gleichen code-Datei, die bedeutet, dass keine externe Bibliothek. So etwas wie dieses:
Diese erfolgreich kompiliert.
Daher vermute ich, dass der compiler nicht bewusst ist, wird die vollständige definition tblkp_Role.
Ich würde vorschlagen, re-Gebäude der Bibliothek und re-Referenzierung es erneut (überprüfen Sie Auch Referenz-Pfad, um sicherzustellen, dass Sie nicht versehentlich verweisen auf ältere version).
Habe ich vor ähnlichen Problemen mit partiellen Klassen, die automatisch erstellt werden, indem Sie EF in der DB first-Ansatz speziell, wenn ich versuchte, Sie zu definieren Metadaten-Klassen.