C# 有没有更好的方法来实现一个可继承的方法,该方法返回一个继承该类类型的对象?

C# 有没有更好的方法来实现一个可继承的方法,该方法返回一个继承该类类型的对象?,c#,generics,inheritance,C#,Generics,Inheritance,我试图创建一个基类,指定一个返回的方法,比如说它自己类型的列表。我希望这个方法能在继承类上正常工作,即返回继承类的列表 这是我能想到的唯一办法 public abstract class Base<T> where T : Base<T> { public List<T> getList() { return new List<T>(); } } public class Foo : Base<Foo> { }

我试图创建一个基类,指定一个返回的方法,比如说它自己类型的列表。我希望这个方法能在继承类上正常工作,即返回继承类的列表

这是我能想到的唯一办法

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(); 

如果切换到
IList
界面,则可以在
对象上定义扩展方法。
(您不能返回
List
或将
List
用作绘图类型)

然后,整个应用程序中的每个类都将使用
MakeList
方法:

扩展方法:

static class Class1
{
    public static IList MakeList(this Object t)
    {
        var listType = typeof(List<>);
        var finalType = listType.MakeGenericType(t.GetType());
        var instance = Activator.CreateInstance(finalType);
        return (IList)instance;
    }
}

我认为主要的问题是这些方法不属于实际的实体,而是应该由您的存储库服务定位器提供(好吧,它根本不必是定位器,理想情况下您只需要有一个组合根并通过构造函数注入所有repo依赖项)

但其想法是为crud操作提供一个通用的基本回购接口:

public interface IRepo<T>
{
    T Get(long id);
    IList<T> GetAll();
    void Save(T instance);
    ... 
}
公共接口IRepo
{
T Get(长id);
IList GetAll();
无效保存(T实例);
... 
}
以及特定实体的特定接口:

public interface IFooRepo : IRepo<Foo>
{
    // additional Foo-specific stuff, if needed
}
公共接口IFooRepo:IRepo
{
//如有需要,可添加特定于Foo的内容
}
这允许您有一个通用的基本抽象实现:

public abstract class BaseRepo<T> : IRepo<T>
{
    // provide default implementations for Load, Save and common stuff
}
公共抽象类BaseRepo:IRepo
{
//提供加载、保存和常见内容的默认实现
}
然后,您的特定存储库继承基类并可选地实现特定方法(请注意,该类不应在任何地方直接实例化,而应通过DI容器实例化):

FooRepo类:BaseRepo、IFooRepo
{
//不需要重新实现任何东西,除了特定于Foo的东西
} 
最后,您还有您的服务定位器(免责声明:它通常用作单例,但实际上不应该):

//获取服务定位器
var repoFactory=GetRepoFactory();
//通过DI获得实际回购
var repo=repoFactory.GetRepo();
//做事
var foo=repo.FindAll();

因此,我的主要意见是,我上一个代码片段中的
GetRepo
方法不属于POCO实体。显示了一个带有EF的存储库模式示例(跳到“实现通用存储库和工作类单元”部分),尽管我更希望通过DI将repo注入控制器,问题是没有任何东西阻止您编写
类栏:Base
。当这个基类本身几乎不可能使用时,您为什么想要基类?当不使用抽象时,抽象有什么意义?@Euphoric:代码重用?您将如何“单独”使用实际的
抽象类?@Groo您能更具体一点吗?重复使用什么?重用在哪里?我已经把基础抽象化了。我最初没有这样做的唯一原因是我想让这个例子尽可能简单。这个答案有几个问题,IMHO:1)OP想创建一个强类型列表,否则他的方法就是
public IList getList()
,他根本不需要泛型,2)这样会丢失所有类型安全性,并且在尝试向列表中添加不同类型的对象时,很容易出现运行时异常,而OP可能正试图避免这种情况。@Groo(2)无论何时在运行时尝试生成泛型集合,都会丢失类型安全性。即使是动态创建的,也需要确保没有添加超出范围的内容。只有在设计期间已知类型时,才能提供真正的类型安全性。在任何其他情况下,您都需要捕获(并处理)无效类型——您也可以使用建议的实现来完成这一点。(好的,C#没有类型擦除功能,所以与Java相比,它有点超前。)服务定位器看起来确实是解决我的问题的好方法。
public interface IFooRepo : IRepo<Foo>
{
    // additional Foo-specific stuff, if needed
}
public abstract class BaseRepo<T> : IRepo<T>
{
    // provide default implementations for Load, Save and common stuff
}
class FooRepo : BaseRepo<Foo>, IFooRepo
{
    // no need to re-implement anything except Foo-specific stuff
} 
// get the service locator
var repoFactory = GetRepoFactory();

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

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