我有一个我的所有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>
?我希望我只需要在方法中进行更改,也许需要抽象类定义,用法应该没问题。
更新 通过一个非常有用的响应,我有一个稍微改进的例子,但一个有趣的困境:
我现在定义了这个,我在 T 上没有任何in
或out
,因为如果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;
答案 0 :(得分:2)
C#4.0在使用委托和接口时支持协方差和逆变。 How is Generic Covariance & Contra-variance Implemented in C# 4.0?
因此,如果你可以使用带有接口的泛型委托Lazy作为参数,那么试试这样的事情:
//covariance then you can save Giraffe as SicilianGiraffe but you cannot save Giraffe as Animal; contr-variance realization is not imposible in your case(just theoreticaly)
public interface ISabaDAO<out T> where T: BaseModel{
int retrieveID(BaseModel);
T SaveData(BaseModel);
}
public abstract class SabaAbstractDAO<T> : ISabaDAO<T>{
...
// in this case Lazy should be covariance delegate too
// delegate T Lazy<out T>();
public K GetIdOrSave<K>(K item, Lazy<ISabaDAO<BaseModel>> lazyitemdao) where K : BaseModel
{
...
return (K)itemdao.SaveData(item);// is not safe
...
}
}
public class Course : BaseModel{}
public class SabaCourseDAO : SabaAbstractDAO<Course>{}
//so you can cast SabaCourseDAO to ISabaDAO<Course> and ISabaDAO<Course> to ISabaDAO<BaseModel>
// then next invoking should be valid
GetIdOrSave(new Course (), new Lazy<ISabaDAO<Course>>(() =>
{
return new SabaCourseDAO() { Dao = Dao };
})
无法检查。我没有VS2010。