目前我遇到了这个问题,我尝试为我的.NET应用程序设计一个DAL,后来将使用某种NoSQL数据库。
我现在评估的NoSQL数据库有时在用作主键的类型上有所不同。例如,MongoDB使用专有ObjectID
,而RavenDB使用公共string
。
所以我的问题是,我如何设计这样一个可以处理不同类型域模型ID的DAL。
我的第一个方法是制作通用域模型。 这看起来像这样:
// Domain Model
public class Filter<TId> {
public TId Id { get; set; }
// ...
}
// DAO-interface
public interface IFilterDao<TId> {
bool Persist(Filter<TId>);
// ...
}
// This is where the problems begin
public static class DAOFactory {
public static IFilterDAO<T> GetFilterDAO<T>() {
// Implementation of IFilterDAO<T> can't be instantiated because types must be known at compile time
}
}
DAO-Factory方法中的注释已经描述了问题:我无法在运行时定义T
,因为相应的代码是在编译时生成的。
我的第二种和第三种方法是将Id
定义为object
或dynamic
。 RavenDB无法与object
一起使用,因为它需要一个字符串。使用dynamic
我无法将lambdas传递给RavenDB API(编译器错误“表达式树可能不包含动态操作”)。
构建表达式树而不是使用lambdas实际上是最后的出路,因为它更耗时。
所以我完全陷入困境,我希望有人可以帮助我。 提前谢谢。
更新:我终于让RavenDB与object
一起使用,但使用object
并不是一个令人满意的解决方案。
答案 0 :(得分:2)
如果你在编译时知道类型,你可以解决静态类中的问题,对吗?这意味着,必然,您将需要为每个底层数据库实现一个DaoFactory实现。
答案是你不应该使用factory pattern - 相反,你应该使用abstract factory pattern。
public class Filter<TId> {
public TId Id { get; set; }
}
public interface IFilterDao<TId> {
bool Persist(Filter<TId>);
}
// Note: Can't be static since polymorphism requires an instance!
public abstract class DaoFactory<TId> {
public abstract IFilterDao<TId> GetFilterDao<TId>();
}
public sealed class MongoDBDaoFactory : DaoFactory<ObjectID> {
public override IFilterDao<ObjectID> GetFilterDao<ObjectID>() { /* ... */ }
}
public sealed class RavenDBDaoFactory : DaoFactory<String> {
public override IFilterDao<String> GetFilterDao<String>() { /* ... */ }
}
我必须做类似的事情并尝试使用dependency injection pattern来选择在运行时使用的适当实现,但由于泛型问题,这实际上很难做到。 抽象工厂是最好的方式。