如何在泛型 class 的具体 class 中引用类型
how to reference the Type in the Concrete class of a generic class
我找到了以下示例,对此我有一个跟进问题。
stack overflow question
问题的现有代码是
public interface IRepository<T> where T : EntityObject
{
RepositoryInstructionResult Add(T item);
RepositoryInstructionResult Update(T item);
RepositoryInstructionResult Delete(T item);
}
public class Repository<T> : IRepository<T> where T : EntityObject
{
virtual RepositoryInstructionResult Add(T item)
{ //implementation}
virtual RepositoryInstructionResult Update(T item);
{ //implementation}
virtual RepositoryInstructionResult Delete(T item);
{ //implementation}
}
public class BarRepository : Repositorybase<Bar>
{
public override RepositoryInstructionResult Update(Bar item);
{
//Call base method if needed
//Base.Update(item);
//implement your custom logic here
}
}
我想做的是将 Update 方法更改为
public class BarRepository : Repositorybase<Bar>
{
// T is of Type Bar
public override RepositoryInstructionResult Update(T item);
{
//implement your custom logic here
}
}
问题:有没有办法将 BarResposity : Repositorybase<Bar>
中的泛型类型暴露给 BarRepository 中的方法?
在构建具体内容时寻找“搜索和替换”的更好替代方法 class(例如,将 BarRespository 复制为 FooRepository,并将所有引用从 Bar 更改为 Foo)。我宁愿只在一个地方更改类型。
(edit) 用法需要保持为
var obj = new BarRepository();
恕我直言,任何 GENERIC 存储库都是浪费时间,但如果您决定使用它,这有什么问题
public class BarRepository<T> : Repository<Bar> where T : class
{
public override void Update(Bar item)
{
}
public void Update(T item)
{
}
}
更新
它看起来很奇怪,但既然 OP 想要它,您也可以创建此代码
public class BarRepository<T> : Repository<Bar> where T : Bar
{
public override void Update(Bar item)
{
Console.WriteLine("it is Bar");
}
// T is of Type Bar
public void Update(T item)
{
Console.WriteLine("it is T");
}
}
测试
public class Bar { }
public class NoBar { }
var barRep= new BarRepository<Bar>();
barRep.Update(new Bar()); // "it is T"
var noBarRep= new BarRepository<NoBar>(); // ERROR!
更新 2
因为如果你想要
var rep = new BarRepository();
var result= rep.Update(new Bar());
你可以按照你已经做过的方式去做
public class BarRepository : Repositorybase<Bar>
{
public override RepositoryInstructionResult Update(Bar item);
{
return base.Update(item);
}
}
PS
如果你还不满意,请看我回答的开头,忘记通用存储库。像最专业的开发人员一样使用自定义的。
请注意,如果您无论如何要覆盖所有 Add/Update/Delete,您可以在 RepositoryBase 中将它们设为抽象,然后 vs 建议是您的朋友:
如果所有具体 classes 之间存在共享逻辑,您可以将其放在抽象 class 中并改写抽象受保护的方法。
编辑:
op 要求提供可以做到这一点的代码。这应该可以工作。但是如果你想要一个新的具体实现,你现在必须创建 2 classes
public class BarRepository<T> : RepositoryBase<T> where T : Bar
{
public override int Add(T item)
{
throw new NotImplementedException();
}
public override int Update(T item)
{
throw new NotImplementedException();
}
public override int Delete(T item)
{
throw new NotImplementedException();
}
}
public class BarRepository : BarRepository<Bar>
{
}
另外,如果 classes 是如此相似以至于复制粘贴和替换就足够了,也许逻辑不应该在单独的 classes 中而是在通用的 class 中?你能举个 2 class 的例子吗?
编辑 2:另一个肮脏的技巧是使用 lambda,尽管我个人不知道是否会这样做:
public abstract class RepositoryBase<T>
{
public Func<T, int> Add { get; protected set; }
public Func<T, int> Update { get; protected set; }
public Func<T, int> Delete { get; protected set; }
}
public class BarRepository : RepositoryBase<Bar>
{
public BarRepository()
{
Add = i => 6;
Update = i => 7;
Delete = i => 8;
}
}
有点hack,但是您可以使用using
别名来定义实体类型:
using MyType = Bar;
public class BarRepository : Repositorybase<MyType>
{
public override RepositoryInstructionResult Update(MyType item);
{
return base.Update(item);
}
}
现在,当您复制到 Foo.cs
时,您只需将 using 指令更改为
using MyType = Foo;
但是,我会尝试尽可能多地重用通用代码,因为仅通过查看方法根本不清楚 MyType
是什么。 find.replace 定义自定义操作的新存储库类型没有错 - 您只是想将重复次数保持在最低限度。
我找到了以下示例,对此我有一个跟进问题。
stack overflow question
问题的现有代码是
public interface IRepository<T> where T : EntityObject
{
RepositoryInstructionResult Add(T item);
RepositoryInstructionResult Update(T item);
RepositoryInstructionResult Delete(T item);
}
public class Repository<T> : IRepository<T> where T : EntityObject
{
virtual RepositoryInstructionResult Add(T item)
{ //implementation}
virtual RepositoryInstructionResult Update(T item);
{ //implementation}
virtual RepositoryInstructionResult Delete(T item);
{ //implementation}
}
public class BarRepository : Repositorybase<Bar>
{
public override RepositoryInstructionResult Update(Bar item);
{
//Call base method if needed
//Base.Update(item);
//implement your custom logic here
}
}
我想做的是将 Update 方法更改为
public class BarRepository : Repositorybase<Bar>
{
// T is of Type Bar
public override RepositoryInstructionResult Update(T item);
{
//implement your custom logic here
}
}
问题:有没有办法将 BarResposity : Repositorybase<Bar>
中的泛型类型暴露给 BarRepository 中的方法?
在构建具体内容时寻找“搜索和替换”的更好替代方法 class(例如,将 BarRespository 复制为 FooRepository,并将所有引用从 Bar 更改为 Foo)。我宁愿只在一个地方更改类型。
(edit) 用法需要保持为
var obj = new BarRepository();
恕我直言,任何 GENERIC 存储库都是浪费时间,但如果您决定使用它,这有什么问题
public class BarRepository<T> : Repository<Bar> where T : class
{
public override void Update(Bar item)
{
}
public void Update(T item)
{
}
}
更新
它看起来很奇怪,但既然 OP 想要它,您也可以创建此代码
public class BarRepository<T> : Repository<Bar> where T : Bar
{
public override void Update(Bar item)
{
Console.WriteLine("it is Bar");
}
// T is of Type Bar
public void Update(T item)
{
Console.WriteLine("it is T");
}
}
测试
public class Bar { }
public class NoBar { }
var barRep= new BarRepository<Bar>();
barRep.Update(new Bar()); // "it is T"
var noBarRep= new BarRepository<NoBar>(); // ERROR!
更新 2
因为如果你想要
var rep = new BarRepository();
var result= rep.Update(new Bar());
你可以按照你已经做过的方式去做
public class BarRepository : Repositorybase<Bar>
{
public override RepositoryInstructionResult Update(Bar item);
{
return base.Update(item);
}
}
PS
如果你还不满意,请看我回答的开头,忘记通用存储库。像最专业的开发人员一样使用自定义的。
请注意,如果您无论如何要覆盖所有 Add/Update/Delete,您可以在 RepositoryBase 中将它们设为抽象,然后 vs 建议是您的朋友:
如果所有具体 classes 之间存在共享逻辑,您可以将其放在抽象 class 中并改写抽象受保护的方法。
编辑: op 要求提供可以做到这一点的代码。这应该可以工作。但是如果你想要一个新的具体实现,你现在必须创建 2 classes
public class BarRepository<T> : RepositoryBase<T> where T : Bar
{
public override int Add(T item)
{
throw new NotImplementedException();
}
public override int Update(T item)
{
throw new NotImplementedException();
}
public override int Delete(T item)
{
throw new NotImplementedException();
}
}
public class BarRepository : BarRepository<Bar>
{
}
另外,如果 classes 是如此相似以至于复制粘贴和替换就足够了,也许逻辑不应该在单独的 classes 中而是在通用的 class 中?你能举个 2 class 的例子吗?
编辑 2:另一个肮脏的技巧是使用 lambda,尽管我个人不知道是否会这样做:
public abstract class RepositoryBase<T>
{
public Func<T, int> Add { get; protected set; }
public Func<T, int> Update { get; protected set; }
public Func<T, int> Delete { get; protected set; }
}
public class BarRepository : RepositoryBase<Bar>
{
public BarRepository()
{
Add = i => 6;
Update = i => 7;
Delete = i => 8;
}
}
有点hack,但是您可以使用using
别名来定义实体类型:
using MyType = Bar;
public class BarRepository : Repositorybase<MyType>
{
public override RepositoryInstructionResult Update(MyType item);
{
return base.Update(item);
}
}
现在,当您复制到 Foo.cs
时,您只需将 using 指令更改为
using MyType = Foo;
但是,我会尝试尽可能多地重用通用代码,因为仅通过查看方法根本不清楚 MyType
是什么。 find.replace 定义自定义操作的新存储库类型没有错 - 您只是想将重复次数保持在最低限度。