我有以下DBML修改(我使用Linq to SQL作为DAL)。
public interface ILinqSQLObject { }
// these are objects from SQL Server mapped into Linq to SQL
public partial class NEWDEBT : ILinqSQLObject { }
public partial class OLDDEBT : ILinqSQLObject { }
public partial class VIPDEBT : ILinqSQLObject { }
有了这个,我可以更好地操纵我的Linq对象在其他区域。
我刚刚完成了一个IRepository模式实现。
public interface IDebtManager<T>
{
IQueryable<T> GetAllDebts();
IQueryable T GetSpecificDebt(System.Linq.Expressions.Expression<Func<T, bool>> predicate);
void Insert(T debt);
// other methods
}
public class DebtManager<T> : IDebtManager<T> where T : class, ILinqSQLObject
{
DebtContext conn = new DebtContext();
protected System.Data.Linq.Table<T> table;
public DebtManager()
{
table = conn.GetTable<T>();
}
public void Insert(T debt)
{
throw new NotImplementedException();
}
public IQueryable<T> GetSpecificDebt(System.Linq.Expressions.Expression<Func<T, bool>> predicate)
{
return table.Where(predicate);
}
public IQueryable<T> GetAllDebts()
{
return table;
}
}
这完美无瑕。但是,有时在编译时我不知道我将使用哪个特定的表。为此,我试图为我的DebtManager创建一个简单的通用工厂。
public static class DebtFactoryManager
{
public static DebtManager<ILinqSQLObject> GetDebtManager(string debtType)
{
switch (debtType)
{
case "New Client":
return new DebtManager<NEWDEBT>();
case "Old Client":
return new DebtManager<OLDDEBT>();
case "VIP Client":
return new DebtManager<VIPDEBT>();
default:
return new DebtManager<NEWDEBT>();
}
return null;
}
}
然而它不起作用。它说我不能'隐含地将DebtManager<NEWDEBT>
转换为DebtManager<ILinqSQLObject>
',但是如果NEWDEBT实现ILinqSQLObject,为什么编译器不能识别它?显然我犯了一些错误,但我看不到它。
答案 0 :(得分:0)
这个错误是由于泛型不暗示支持协方差这一事实造成的;也就是说,将特定的泛型参数类型视为其基类型之一。
了解这一点。首先,您可以定义泛型DebtManager继承的非泛型DebtManager基类,并返回该基类。其次,您可以定义DebtManager实现的通用接口;通用接口可以通过在泛型类型参数之前使用关键字out
来定义为协变。
编辑:让我们回到主要需求。在编译时,您可能不知道需要使用哪种类型的对象,因此您不知道需要哪个存储库。那么,我建议您使用每个数据库的存储库来代替每个存储库的存储库。 DebtManager已经是任何Linq to SQL类型的通用名称;那么为什么不把这些方法设为通用的,允许它们从调用到调用是通用的?
public interface IRepository<T> where T:class, ILinqSqlObject
{
IQueryable<TSpec> GetAllDebts<TSpec>() where TSpec : T;
IQueryable<TSpec> GetSpecificDebt<TSpec>(System.Linq.Expressions.Expression<Func<TSpec, bool>> predicate) where TSpec : T;
void Insert<TSpec>(TSpec debt) where TSpec:T;
// other methods
}
interface IDebtObject : ILinqSqlObject
public interface IDebtManager:IRepository<IDebtObject> { }
public class DebtManager:IDebtManager
{
DebtContext conn = new DebtContext();
public DebtManager()
{
}
public void Insert<T>(T debt) where T:IDebtObject
{
throw new NotImplementedException();
}
public IQueryable<T> GetSpecificDebt(System.Linq.Expressions.Expression<Func<T, bool>> predicate) where T:IDebtObject
{
return conn.GetTable<T>().Where(predicate);
}
public IQueryable<T> GetAllDebts<T>() where T:IDebtObject
{
return conn.GetTable<T>();
}
}