我正在尝试创建一个基类,它指定一个返回的方法,比如一个自己类型的列表。我希望这个方法在继承类时正常工作,即。返回继承类的列表。
这是我能想到的唯一方法。
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
继承自身作为类型的基础?说在List<this>
中指定Base
或类似内容?
正如Groo指出的那样,理想情况下我不希望class Bar : Base<Foo>
成为可能。
实际问题我正在尝试解决更新问题:
基本上,我正在尝试使用Entity Framework代码优先的POCO类来返回自己的模型存储,这样我就可以编写一般代码来处理POCO类的验证,并为API保存。
模型存储封装了基本的CRUD操作,以便我们可以覆盖访问方法来执行其他操作,例如隐藏软删除的项目。
在我在验证类和DTO代码(数据传输对象 - 在WSDL API和POCO之间进行转换)中实现相同的getModelStore
方法后,我决定这样做。
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);
答案 0 :(得分:1)
如果切换到IList
界面,则可以在Object
上定义扩展方法。
(您不能返回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;
}
}
用法:
Object o = new Object();
IList list = o.MakeList();
list.Add(new Object());
list.Add(new Object());
MessageBox.Show(list.Count.ToString());
String s = "";
IList stringList = s.MakeList();
stringList.Add("hello");
stringList.Add("world");
MessageBox.Show(stringList.Count.ToString());
答案 1 :(得分:1)
我认为主要的问题是这些方法不属于实际实体,而应该由您的存储库服务定位器提供(嗯,它根本不必是定位器,理想情况下你只需要有一个组合根,并通过构造函数注入所有repo依赖项。)
但我们的想法是为crud操作提供一个共同的基础repo接口:
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
}
这允许您有一个共同的基本抽象实现:
public abstract class BaseRepo<T> : IRepo<T>
{
// provide default implementations for Load, Save and common stuff
}
然后您的特定存储库继承基类并可选地实现特定方法(请注意,此类不应直接在任何地方实例化,而是通过DI容器实现):
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();
所以,我的主要评论是我上一个代码段中的GetRepo
方法不属于POCO实体。 This article显示了一个带EF的存储库模式示例(跳到“实现通用存储库和工作单元类”部分),虽然我更希望通过DI将repo注入控制器,而不是在控制器构造函数中被new
编译。