![](/img/trans.png)
[英]Getting Child type in base class to pass as type parameter to another method
[英]Getting child class type from parent class parameter
我将有一个对象的多种“类型”,我真的不确定如何最好地检索/保存这些多种类型,而无需为每种类型单独保存/检索。
我的课程:
public class Evaluation {
public int Id
public string Comment
}
public class EvaluationType_1 : Evaluation {
public string field
}
public class EvaluationType_1 : Evaluation {
public string field
}
我想在我的存储库中做什么:
public interface IEvaluationRepository {
public Evaluation getEvaluation(int id);
public SaveEvaluation(Evaluation);
}
在 get/save 方法中:
// Save/get common fields
Id
Comments
// Get child type, perform switch
Type childType = ???
switch(childType) {
// Set child-specific fields
}
我宁愿不添加“类型”列,因为我在数据库的另一部分中有这个,而且我不太喜欢它
如有必要,这里有更多信息进行澄清。
我喜欢使用接口和泛型的想法,我真的不知道如何将它们合并到我的存储库模式中。
当我调用getEvaluation
,我希望它返回一个抽象的评估,但我正在努力处理这段代码。 与保存相同。
丹尼尔正在帮助我磨练我到底要问什么。
数据库:
Evaluations
Id (PK)
Comment
EvaluationType1
Id (FK to Evaluations.Id)
Field
EvaluationType1
Id (FK to Evaluations.Id)
Field
所以,在getEvaluation(int id)
,我需要弄清楚他们想要什么类型的评估。 这是否意味着我应该传入一个类型? 在saveEvaluation
也是如此,但我可以做一个开关/函数映射来查看它是什么Type
。
试试这个
public interface ISaveable {
void SaveFields();
}
public abstract class Evaluation : ISaveable {
public int Id
public string Comment
public virtual void SaveFields() {
//Save ID and Comments
}
}
public class EvaluationType_1 : Evaluation {
public string field1
public override void SaveFields() {
//Save field1
base.SaveFields();
}
}
public class EvaluationType_2 : Evaluation {
public string field2
public override void SaveFields() {
//Save field2
base.SaveFields();
}
}
然后,您可以拥有一个 ISaveable 集合,例如List<ISaveable>
并在每个集合上调用 SaveFields,而不管它们的类型如何。 您现在正在针对接口而不是针对具体类型进行编程。 代码解耦的第一步。
编辑:响应您的评论 在您的存储库中,您将不再针对评估类进行编程。 相反,您将针对它实现的接口中的方法进行编程:
代替:
public interface IEvaluationRepository {
public Evaluation getEvaluation(int id);
public SaveEvaluation(Evaluation);
}
你可能有:
public interface ISaveableRepository {
public ISaveable getSavable(int id);
public Save(ISaveable saveable);
}
存储库的实现可能类似于:
public class SaveableEvaluationRepository : ISaveableRepository {
public ISaveable getSavable(int id) {
//Add your logic here to retrieve your evaluations, although I think that
//this logic would belong elsewhere, rather than the saveable interface.
}
public Save(ISaveable saveable) {
saveable.SaveFields();
}
}
您的问题尚不清楚,但根据我的理解,您正在寻找对象的类型。 这是你如何做到的。
EvaluationType_1 objOfEvalType1 = new EvaluationType_1();
Type childType = objOfEvalType1.GetType();
如果您需要基类/父类中的子类类型,请按如下方式更新您的评估类。
public class Evaluation {
public int Id;
public string Comment;
//call this.GetType() anywhere you wish to get the type of the object.
public Type MyType = this.GetType();
}
这听起来像是泛型的一个很好的候选者,并且很多存储库和 ORM 框架都使用它们。
public interface IEvaluationRepository<TEvaluation>
{
public TEvaluation getEvaluation(int id);
public SaveEvaluation(TEvaluation evaluation);
}
您可能还需要一个 EvaluationBase 类来处理常见功能,并限制您的接口仅采用 EvaluationBase 类:
public interface IEvaluationRepository<TEvaluation> where TEvaluation : EvaluationBase
...
public class SomeEvaluation : EvaluationBase
{
}
它将避免识别和跟踪对象类型的大部分或全部问题。
Object.GetType
返回当前实例的确切运行时类型 - 它不考虑关联变量的声明类型:
Type type = evaulation.GetType();
// Note that you can't switch on types
if (type == typeof(DerivedEvaluation1)) {
// Perform custom operations
}
else if (type == typeof(DerivedEvaluation2)) {
// Perform custom operations
}
// Etc.
我将您的问题解释为询问一种方便的方法来调度自定义保存逻辑,而无需对子对象的类型进行“混乱”切换。 如果您想要的只是一种简单的方法来确定类型参数,您可以使用is
关键字。
有几种基于运行时类型的调度逻辑的方法。
一个是你总是可以为每个特定类型创建一个Save
函数的调度字典:
private static readonly Dictionary<Type,Action<Evaluation>> s_SaveFunctions =
new Dictionary<Type,Action<Evaluation>>();
s_SaveFunctions[typeof(ChildA)] = SaveChildA;
s_SaveFunctions[typeof(ChildB)] = SaveChildB;
// .. and so on.
public SaveEvaluation( Evaluation eval )
{
// .. common save code ...
// cal the appropriately typed save logic...
s_SaveFunctions[eval.GetType()]( eval );
}
private static void SaveChildA( Evaluation eval ) { ... }
private static void SaveChildB( Evaluation eval ) { ... }
在 .NET 4 中,您可以使用dynamic
来实现相同的更清晰版本:
public SaveEvaluation( Evaluation eval )
{
// .. common save logic ..
dynamic evalDyn = eval;
SaveChild( evalDyn );
}
private void SaveChild( ChildA eval ) { ... }
private void SaveChild( ChildB eval ) { ... }
请注意SaveChild
方法如何都具有相同的名称,但只是由它们的参数类型重载。 SaveEvaluation
方法中使用的dynamic
参数将在运行时进行评估,并分派给适当的重载。
您可以将您的方法设为虚拟 - 调用将根据实际运行时类型分派到正确的方法。
public class Evaluation
{
public Int32 Id { get; set; }
public String Comment { get; set; }
public virtual void Save()
{
// Save the common information.
this.SaveToDatabase(this.Id);
this.SaveToDatabase(this.Comment);
}
private void SaveToDatabase(Object value)
{
// Left as an exercise for the reader... :D
}
}
public class EvaluationType1 : Evaluation
{
public String Foo { get; set; }
public override void Save()
{
// Save the common information.
base.Save();
// Save the specific information here.
this.SaveToDatabase(this.Foo);
}
}
public class EvaluationType2 : Evaluation
{
public String Bar { get; set; }
public override void Save()
{
// Save the common information.
base.Save();
// Save the specific information here.
this.SaveToDatabase(this.Bar);
}
}
也许您也可以使基类抽象。 此外,您通常应该避免将字段设为可公开访问 - 这可能会将维护代码变成一场噩梦,因此我在示例中使用了属性。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.