1

我有一个泛型类,我的所有 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

    {

那么,如何使用方差(如果需要)和泛型来编译它,这样我就可以有一个非常通用的方法,只适用于BaseModeland AbstractDAO<BaseModel>?我希望我只需要在方法和抽象类定义中进行更改,用法应该没问题。

更新: 有一个非常有用的回应,我有一个稍微改进的例子,但一个有趣的困境:

我现在已经定义了这个,并且我没有任何inor outon T这里因为我得到了矛盾的错误,如果out T我得到它必须是contravariantly valid并且如果in Tthen 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;
4

1 回答 1

2

在使用委托和接口时,C# 4.0 支持协变和逆变。 C# 4.0 中如何实现泛型协方差和逆变换?

因此,如果您可以将通用委托 Lazy 与 Interface 作为参数一起使用,请尝试以下操作:

//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。

于 2010-05-21T09:24:28.583 回答