У меня есть универсальный класс, из которого происходят все мои классы DAO, который определен ниже. У меня также есть базовый класс для всех моих сущностей, но он не является общим.
Метод GetIdOrSave
будет отличаться от того, который я определил SabaAbstractDAO
, так как я пытаюсь получить первичный ключ для выполнения отношений с внешним ключом, поэтому эта функция выходит либо для получения первичного ключа или сохраните объект, а затем получите первичный ключ.
В последнем фрагменте кода есть решение о том, как он будет работать, если я избавлюсь от общей части, поэтому я думаю, что это можно решить с помощью дисперсии, но я не могу понять, как написать интерфейс, который будет компилироваться .
public abstract class SabaAbstractDAO<T> :ISabaDAO<T> where T:BaseModel
{
...
public K GetIdOrSave<K>(K item, Lazy<ISabaDAO<BaseModel>> lazyitemdao)
where K : BaseModel
{
...
}
Я получаю эту ошибку при попытке скомпилировать:
Argument 2: cannot convert from 'System.Lazy<ORNL.HRD.LMS.Dao.SabaCourseDAO>' to 'System.Lazy<ORNL.HRD.LMS.Dao.SabaAbstractDAO<ORNL.HRD.LMS.Models.BaseModel>>'
Я пытаюсь назвать это так:
GetIdOrSave(input.OfferingTemplate,
new Lazy<ISabaDAO<BaseModel>>(
() =>
{
return (ISabaDAO<BaseModel>)new SabaCourseDAO() { Dao = Dao };
})
);
Если я изменю определение на это, оно сработает.
public K GetIdOrSave<K>(K item, Lazy<SabaCourseDAO> lazyitemdao) where K : BaseModel
{
Итак, как я могу получить это для компиляции с использованием дисперсии (при необходимости) и обобщений, чтобы у меня был очень общий метод, который будет работать только с BaseModel
и AbstractDAO<BaseModel>
? Я ожидаю, что мне нужно только внести изменения в метод и, возможно, абстрактное определение класса, использование должно быть в порядке.
UPDATE:
С очень полезным ответом у меня есть немного улучшенный пример, но интересная дилемма:
У меня есть это определение сейчас, и у меня нет in
или out
здесь T , потому что я получаю ошибки, которые противоречат, если out T
, тогда я получаю, что это должно быть contravariantly valid
, а если in T
, то covariantly valid
, поэтому я сделал его инвариантным, так как кажется, что VS2010 не может его понять.
public interface ISabaDAO<T> where T:BaseModel
{
string retrieveID(T input);
T SaveData(T input);
}
Я получаю эту ошибку, хотя она компилируется:
System.InvalidCastException: Unable to cast object of type 'ORNL.HRD.LMS.Dao.SabaCourseDAO' to type 'ORNL.HRD.LMS.Dao.ISabaDAO`1[ORNL.HRD.LMS.Models.BaseModel]'.
Я исправил два фрагмента кода выше, но похоже, что дисперсия не сработает, как я и надеялся.
Я пробовал это:
public delegate K GetIdOrSave<out K>(K item, Lazy<ISabaDAO<BaseModel>> lazyitemdao)
where K : BaseModel;
но я получаю ту же проблему, что и с интерфейсом, если я поставлю out
, он жалуется, поэтому я ставлю in
и жалобу противоположную.
Я думаю, я мог бы заставить это работать, если бы это было законно:
public delegate K GetIdOrSave<K>(in K item, out Lazy<ISabaDAO<BaseModel>> lazyitemdao)
where K : BaseModel;