有没有更好的方法来实现可继承的方法,该方法返回从该类类型继承的对象? [英] Is there a better way to implement an inheritable method that returns an object inheriting off that class type?

查看:69
本文介绍了有没有更好的方法来实现可继承的方法,该方法返回从该类类型继承的对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建一个基类,该基类指定一个返回的方法,例如其自身类型的列表.我希望该方法在继承类上正确工作.返回继承的类的列表.

I am trying to make a base class that specifies a method that returns, say a list of its own type. I want this method to work correctly on inheriting classes, ie. to return a list of the inherited class.

这是我想到的唯一方法.

This is the only way I can think of doing it.

public abstract class Base<T>
  where T : Base<T>
{
  public List<T> getList()
  {
    return new List<T>();
  }
}

public class Foo : Base<Foo>
{
}

var foo = new Foo();

// Should return List<Foo>
var fooList = foo.getList(); 

是否有一种更好的方法,它不需要Foo继承其自身作为类型的碱基?是要在Base中指定List<this>还是类似名称?

Is there a better way that does not require Foo to inherit off of a base with itself as a type? Say specifying List<this> or similar in Base?

正如Groo所指出的,理想情况下,我不希望class Bar : Base<Foo>成为可能.

As Groo points out, ideally I do not want class Bar : Base<Foo> to be possible.

我要解决的实际问题:

基本上,我试图获取Entity Framework代码优先的POCO类以返回其自己的模型存储,以便我可以编写在验证方面通用地处理POCO类并保存API的代码.

Basically, I'm trying to get Entity Framework code-first POCO classes to return their own model stores so that I can write code that handles the POCO classes generically in terms of their validation, and saving for an API.

模型存储区封装了基本的CRUD操作,以便我们可以重写访问方法来做其他事情,例如隐藏软删除的项目.

Model stores encapsulate basic CRUD operations so that we can override the access methods to do additional things like hiding soft-deleted items.

在验证类和DTO代码(数据传输对象-在WSDL API和POCO之间转换)中实现了相同的getModelStore方法后,我决定执行此操作.

I decided to do this after I implemented the same getModelStore method both in the validation class, and in the DTO code (data transfer object - translates between WSDL API and POCO).

public abstract class EntityBase<T>
  where T : EntityBase<T>
{
  public abstract ModelStore<T> getModelStore(Repository repository);
}

public class Foo : EntityBase<Foo>
{
  public override ModelStore<Foo> getModelStore(Repository repository);
  {
    // repository.Foo is a Foo ModelStore
    return repository.Foo;
  }
}

var repo = new Repository();
var foo = new Foo();

// Should return the ModelStore for Foo
var fooList = foo.getModelStore(repo); 

推荐答案

我认为主要的问题是这些方法不属于实际实体,而应该由您的存储库服务定位器提供(嗯,它确实不完全不必是定位器,理想情况下,您只需要具有合成根并通过构造函数注入所有回购依赖项即可.

I believe that the main problem is that these methods don't belong to actual entities, but should be provided by your repository service locator instead (well, it doesn't have to be a locator at all, ideally you would just have a composition root and inject all repo dependencies through constructors).

但是我们的想法是为Crud操作提供一个通用的基本repo接口:

But the idea is to have a common base repo interface for crud operations:

public interface IRepo<T>
{
    T Get(long id);
    IList<T> GetAll();
    void Save(T instance);
    ... 
}

特定实体的特定接口:

public interface IFooRepo : IRepo<Foo>
{
    // additional Foo-specific stuff, if needed
}

这使您可以使用通用的基本抽象实现:

This allows you to have a common base abstract implementation:

public abstract class BaseRepo<T> : IRepo<T>
{
    // provide default implementations for Load, Save and common stuff
}

然后,您的特定存储库会继承基类并有选择地实现特定方法(请注意,该类不应在任何地方直接实例化,而应通过DI容器进行实例化):

And then your specific repositories inherit the base class and optionally implement specific methods (note that this class shouldn't be instantiated directly anywhere, but through a DI container instead):

class FooRepo : BaseRepo<Foo>, IFooRepo
{
    // no need to re-implement anything except Foo-specific stuff
} 

最后,您有了服务定位器(免责声明:它通常用作单例,但实际上不应该使用):

And finally you have your service locator (disclaimer: it's often used as a singleton but it shouldn't actually be):

// get the service locator
var repoFactory = GetRepoFactory();

// get the actual repo through DI
var repo = repoFactory.GetRepo<IFooRepo>();

// do stuff
var foo = repo.FindAll();

所以,我的主要意思是我上一个代码片段中的GetRepo方法不属于POCO实体. new封装.

So, my primary remark is that the GetRepo method in my last code snippet doesn't belong to a POCO entity. This article shows an example of a repository pattern with EF (skip to the "Implement a Generic Repository and a Unit of Work Class" part), although I would prefer the repo to be injected into the controller through DI, instead of being newed inside the controller constructor.

这篇关于有没有更好的方法来实现可继承的方法,该方法返回从该类类型继承的对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆