选择接受 base 或 child class 作为参数的重载方法
Choose overloaded method that accepts base or child class as parameter
标题可能写得不好,因为我真的不知道如何描述我的问题。
我的问题如下所述。
我有两个 classes:
class BaseModel {
public string Name {get; set;}
}
class ChildModel : BaseModel {
public string ChildName {get; set;}
}
第三个 class 我保留上面的实例 classes:
class OverallModel {
public IEnumerable<BaseModel> Models {get; set;}
}
现在我有两个方法:
public MappedBaseModel MapModel(BaseModel source){
var result = new MappedBaseModel();
// do magic for basemodel
}
public MappedBaseModel MapModel(ChildModel source){
var result = new MappedChildModel(); // MappedChildModel is a child of MappedBaseModel
// do magic for childmodel
}
现在,当我像那样遍历 Models
时:
var list = new List<MappedBaseModel>();
foreach(var model in overallModel.Models){
list.Add(MapModel(model));
}
我很困惑,因为代码只调用 MapModel(BaseModel)
,从不调用 MapModel(ChildModel)
。我做了一个变通方法来检查模型是否属于 ChildModel:
foreach ...
if(model is ChildModel)
list.Add(MapModel(model as ChildModel)); // thats just ugly..
else
list.Add(MapModel(model));
我的问题是它看起来很糟糕。我不想检查模型的类型只是为了调用其他重载方法。
你能帮我让它更优雅吗?
我知道我可能没有提供足够的信息。请,如果您需要了解更多信息,请询问,我会尝试更深入地解释。
另外,对不起我的英语!
祝你有个愉快的一天。
这类问题通常可以使用 multiple dispatch 解决,但在您的场景中这可能有点矫枉过正。考虑将单个虚拟 Map()
方法添加到 BaseModel
class:
class BaseModel {
public virtual MappedModelBase Map() {
var result = new MappedBaseModel();
// ...
return result;
}
}
class ChildModel : BaseModel {
public override MappedModelBase Map() {
var result = new MappedChildModel();
// ...
return result;
}
}
然后就是:
var list = new List<MappedBaseModel>();
foreach(var model in overallModel.Models)
list.Add(model.Map());
现在,如果您喜欢 "enterprisey" 东西,这里是执行这种双重调度样式的方法:
public class Mapper
{
public MappedBaseModel MapModel(BaseModel source);
public MappedBaseModel MapModel(ChildModel source);
}
class BaseModel
{
public virtual MappedBaseModel MapWith(Mapper mapper)
{
return mapper.MapModel(this);
}
}
class ChildModel : BaseModel
{
public override MappedBaseModel MapWith(Mapper mapper)
{
return mapper.MapModel(this);
}
}
var mapper = new Mapper();
foreach(var model in overallModel.Models)
list.Add(model.MapWith(mapper));
方法 MapModel
(或其他某个方法)应该被覆盖,在这种情况下不应重载。
by Anton Gogolev 是上述场景应该采用的...
另一种方法是使用 dynamic
类型。你可以简单地做:
list.Add(MapModel((dynamic)model));
它会调用相应的重载。
标题可能写得不好,因为我真的不知道如何描述我的问题。 我的问题如下所述。 我有两个 classes:
class BaseModel {
public string Name {get; set;}
}
class ChildModel : BaseModel {
public string ChildName {get; set;}
}
第三个 class 我保留上面的实例 classes:
class OverallModel {
public IEnumerable<BaseModel> Models {get; set;}
}
现在我有两个方法:
public MappedBaseModel MapModel(BaseModel source){
var result = new MappedBaseModel();
// do magic for basemodel
}
public MappedBaseModel MapModel(ChildModel source){
var result = new MappedChildModel(); // MappedChildModel is a child of MappedBaseModel
// do magic for childmodel
}
现在,当我像那样遍历 Models
时:
var list = new List<MappedBaseModel>();
foreach(var model in overallModel.Models){
list.Add(MapModel(model));
}
我很困惑,因为代码只调用 MapModel(BaseModel)
,从不调用 MapModel(ChildModel)
。我做了一个变通方法来检查模型是否属于 ChildModel:
foreach ...
if(model is ChildModel)
list.Add(MapModel(model as ChildModel)); // thats just ugly..
else
list.Add(MapModel(model));
我的问题是它看起来很糟糕。我不想检查模型的类型只是为了调用其他重载方法。 你能帮我让它更优雅吗? 我知道我可能没有提供足够的信息。请,如果您需要了解更多信息,请询问,我会尝试更深入地解释。 另外,对不起我的英语! 祝你有个愉快的一天。
这类问题通常可以使用 multiple dispatch 解决,但在您的场景中这可能有点矫枉过正。考虑将单个虚拟 Map()
方法添加到 BaseModel
class:
class BaseModel {
public virtual MappedModelBase Map() {
var result = new MappedBaseModel();
// ...
return result;
}
}
class ChildModel : BaseModel {
public override MappedModelBase Map() {
var result = new MappedChildModel();
// ...
return result;
}
}
然后就是:
var list = new List<MappedBaseModel>();
foreach(var model in overallModel.Models)
list.Add(model.Map());
现在,如果您喜欢 "enterprisey" 东西,这里是执行这种双重调度样式的方法:
public class Mapper
{
public MappedBaseModel MapModel(BaseModel source);
public MappedBaseModel MapModel(ChildModel source);
}
class BaseModel
{
public virtual MappedBaseModel MapWith(Mapper mapper)
{
return mapper.MapModel(this);
}
}
class ChildModel : BaseModel
{
public override MappedBaseModel MapWith(Mapper mapper)
{
return mapper.MapModel(this);
}
}
var mapper = new Mapper();
foreach(var model in overallModel.Models)
list.Add(model.MapWith(mapper));
方法 MapModel
(或其他某个方法)应该被覆盖,在这种情况下不应重载。
另一种方法是使用 dynamic
类型。你可以简单地做:
list.Add(MapModel((dynamic)model));
它会调用相应的重载。