【问题标题】:Override property conflict覆盖属性冲突
【发布时间】:2017-01-31 15:41:06
【问题描述】:

我有两个复杂的类:

public class BaseRepository<EntityType> where EntityType : class
{
    protected northwindDataContext context = new northwindDataContext();

    public EntityType Get(object id)
    {
        return context.Set<EntityType>().Find(id);
    }

    public EntityType Save(EntityType entity)
    {
        // Do generic save things
    }
}

public class BaseService<EntityType> where EntityType : class
{
    public BaseRepository<EntityType> repo = new BaseRepository<EntityType>();

    public EntityType Get(object id)
    {
        // Do generic get entities
        return repo.Get(id);
    }
}

然后我有多个“服务”类,有时(并非总是)我需要“替换”存储库以添加一些“额外”功能。

public class UserRepository : BaseRepository<User>
{
    public User Get(object id)
    {
        // Do specific user get including Role DP
        return context.Users.Include("Role").Find(id);
    }
}

public class UserService : BaseService<User>
{
    public UserRepository repo = new UserRepository();
}

使用这种格式,UserService 实例调用 BaseRepository.Get() 而不是 UserRepository.Get()。

我想要做的唯一方法是复制这样的代码:

public class UserService : BaseService<User>
{
    public UserRepository repo = new UserRepository();

    public User Get(object id)
    {
        // This call to UserRepository.Get()
        return repo.Get(id);
    }
}

真正的问题是我有 29 个“存储库”,所以我需要添加“Get(int)”、“Get(predicate)”、“Save(entity)”、“Save(IEnumerable)”、“Delete( entity)" 和 "Delete(IEnumerable)",这会产生一种尴尬的代码。

有没有办法替换BaseService中的“repo”属性,让BaseService方法调用repo子类?

【问题讨论】:

    标签: c# entity-framework


    【解决方案1】:

    听起来您真正想要的是 BaseService&lt;T&gt;.repo 字段(它是一个字段,而不是属性 - 我不鼓励您使用公共字段,但这是另一回事)成为合适的存储库对于类型。这很容易做到——只是不要在BaseService&lt;T&gt; 中创建它。相反,将它传递给构造函数链:

    // Type parameter renamed to follow normal .NET naming conventions
    public abstract class BaseService<T> where T : class
    {
        private readonly BaseRepository<T> repo;
    
        protected BaseService(BaseRepository<T> repo)
        {
            this.repo = repo;
        }
    
        public T Get(object id)
        {
            // Do generic get entities
            return repo.Get(id);
        }
    }
    
    public class UserService : BaseService<User>
    {
        public UserService() : base(new UserRepository())
        {
        }
    }
    

    事实上,如果UserService 没有提供任何其他值,您可能只需要一个非抽象的Service&lt;T&gt; 并带有一个public 构造函数来获取repo。然后你只需使用:

    var userService = new Service<User>(new UserRepository());
    

    例如。

    【讨论】:

    • 最好的部分是现在对 DI 友好。
    • 我确实这样做了,但是如果 BaseRepository 定义了“Get”,我无法覆盖 UseRepository 上的 Get 方法。 BaseRepository.Get() 应该只返回 context.Set().Find(id) 如果被覆盖的仓库没有这个方法。
    • 感谢您所做的一切。我在您的帮助下解决了这个问题,并将“虚拟”添加到 BaseService.Get() 并将“覆盖”添加到 UserService.Get()
    • @Pythonizo:为什么要这样做?在您在问题中显示的代码中,在这两种情况下您都只是调用repo.Get(id) - 那么为什么需要覆盖UserService 中的行为?
    • 我看到了我的错误并在 baseservice 中创建了一个没有参数的构造函数。受保护的 BaseService() { this.repo = new BaseRepository(); }
    猜你喜欢
    • 1970-01-01
    • 2021-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多