我有一个包含实体的域层程序集,它由包含实体存储库实现的数据层程序集引用。在域层组件中,实体被组织在具有根实体和子实体的聚合中。我使子实体不能直接实例化,将它们的构造函数转换为内部。通过这种方式,客户不能在他们身上使用新的运营商,但他们被迫使用工厂。
在数据层程序集中,我为每个实体都有一个存储库(不管它是根实体还是子实体)。存储库是使用泛型实现的,当在GetById和GetAll方法中返回实际实体或实体列表时,问题就出现了。为了让他们创建新实例,我必须在泛型上指定new() 约束。这不会编译,因为new() 约束需要公共无参数构造函数。我尝试使用internalsVisibleTo属性来允许数据层程序集访问域层内部,但它不起作用。
我没有使用EF或其他ORM,而是使用带有非常简单映射库的ADO.NET 。
这是一些示例代码:
namespace DomainLayer {
public class Entity {
internal Entity() {
}
}
}
namespace DataLayer {
public class Repository<T> where T: new() {
public T GetById<T>() {
return new T();
}
}
}
namespace Client {
public class AClientClass {
public void aMethod() {
Entity entity1 = new Entity(); // Not possible, correct
Entity entity2 = new Repository<Entity>().GetById(10); //Not possible, how to fix it???
}
}
}
我得到的编译错误是:
'DomainLayer.Entity' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'DataLayer.Repository<T>'
非常感谢。塞布
在重构代码下方使用 Ed_Chapel 建议:
namespace DomainLayer {
public class Entity {
internal Entity() {
}
}
}
namespace DataLayer {
public class Repository<T> {
private Func<T> _creator;
public Repository(Func<T> creator) {
_creator = creator;
}
public T GetById(int id) {
return _creator();
}
}
}
namespace DataLayer {
public class EntityRepository : Repository<Entity> {
public EntityRepository()
: base(() => new Entity()) {
}
}
}
namespace Client {
public class AClientClass {
public void aMethod() {
Entity entity1 = new Entity(); // Not possible, correct
Entity entity2 = new EntityRepository().GetById(10); //Now working!!!
}
}
}
感谢 Ed_Chapel!