掌握dto polimorphism

时间:2016-01-21 12:12:52

标签: c# generics polymorphism dto solid-principles

我提到我与DTO的工作并没有太多关系。我正在玩DataTransfereObjects上的polimophism。我无法弄清楚一个很好的解决方案,所以我已经使用DataTransfereObjects和不同的逻辑实现,使用Polimorphism,泛型,接口,抽象等来使用这个codeample来掌握polimorphism。

请检查代码。告诉我什么是坏的,可以做得更好或更容易。检查accessmodifier,同时检查SOLID(想想我还没有理解它)。最后它似乎太复杂了,以这种方式解决它是否常见?

实际上,我尝试调用一些(de)序列化程序逻辑,它使用baseDto来导出dtos,而不会丢失它们的特定信息。此代码应该是一个干净的抽象沙箱,用于解决此类问题。

void Main()
{
    var twoIngrDto = new TwoIngredientsDto();
    var threeIngrDto = new ThreeIngredientsDto(); 

    var twoIngrMulAnswerChecker = new TwoIngredientsMultiplicationAnswerChecker();
    var threeIngrAddAnswerChecker = new ThreeIngredientsAdditionAnswerChecker();

    twoIngrMulAnswerChecker.IsTheAnswerCheckImplementationTheAnswer(twoIngrDto); //TRUE .Dump();
    threeIngrAddAnswerChecker.IsTheAnswerCheckImplementationTheAnswer(threeIngrDto); //TRUE .Dump();
    twoIngrMulAnswerChecker.IsTheAnswerCheckImplementationTheAnswer(threeIngrDto); //FALSE .Dump();

    IAnswerCheck answerchecker = new IngredientsAnswerChecker();
    answerchecker.CheckAnswer(twoIngrMulAnswerChecker, twoIngrDto); //TRUE .Dump();
    answerchecker.CheckAnswer(threeIngrAddAnswerChecker, threeIngrDto); //TRUE .Dump();

    /// QUESTION: How can I use the answerchecker 'twoIngrMulAnswerChecker' with the derived DTO 'threeIngrDto'
    /// It failes with following error:
    /// The type 'UserQuery.TwoIngredientsMultiplicationAnswerChecker' cannot be used as 
    /// type parameter 'T' in the generic type or method 'UserQuery.IngredientsAnswerChecker.CheckAnswer<T,DTO>(T, DTO)'. 
    /// There is no implicit reference conversion from 'UserQuery.TwoIngredientsMultiplicationAnswerChecker' 
    /// to 'UserQuery.TheAnswerChecker<UserQuery.ThreeIngredientsDto>'.
    //answerchecker.CheckAnswer(twoIngrMulAnswerChecker, threeIngrDto).Dump();
    answerchecker.CheckAnswer(twoIngrMulAnswerChecker, (TwoIngredientsDto)threeIngrDto).Dump(); // is casting the solution? 
}

interface IAnswerCheck
{
    bool CheckAnswer<T, DTO>(T answerCkecker, DTO ingredientsDto) 
        where T : TheAnswerChecker<DTO>
        where DTO : IngredientDto;
}

public abstract class TheAnswerChecker<T> where T : IngredientDto
{
    internal abstract int TheAnswerCheckImplementation(T answerIngredietsDto);
    private int TheAnswer {get { return 42;} }

    public bool IsTheAnswerCheckImplementationTheAnswer(T answerIngredietsDto)
    {
        return TheAnswer == TheAnswerCheckImplementation(answerIngredietsDto);
    }
}

//generate a base class
public class IngredientsAnswerChecker : IAnswerCheck //: TheAnswerChecker<IngredientDto>
{
    public bool CheckAnswer<T, DTO>(T answerCkecker, DTO ingredientsDto) 
        where T : TheAnswerChecker<DTO>
        where DTO : IngredientDto
    {
        return answerCkecker.IsTheAnswerCheckImplementationTheAnswer(ingredientsDto);
    }
}

public class TwoIngredientsMultiplicationAnswerChecker : TheAnswerChecker<TwoIngredientsDto>
{
    internal override int TheAnswerCheckImplementation(TwoIngredientsDto answerIngredietsDto) //where T : TwoIngredientsDto
    { 
        return answerIngredietsDto.A * answerIngredietsDto.B;
    }
}

public class ThreeIngredientsAdditionAnswerChecker : TheAnswerChecker<ThreeIngredientsDto>
{
    internal override int TheAnswerCheckImplementation(ThreeIngredientsDto answerIngredietsDto)
    {
        return answerIngredietsDto.A + answerIngredietsDto.B + answerIngredietsDto.C;
    }
}

public class IngredientDto
{
    public IngredientDto()
    {
        Id = Guid.NewGuid();
    }
    public Guid Id { get; private set; }
}

public class TwoIngredientsDto : IngredientDto
{
    public virtual int A {get {return 6;}}
    public virtual int B {get {return 7;}} 
}

public class ThreeIngredientsDto : TwoIngredientsDto
{
    public override int B {get {return 24;}} 
    public int C {get {return 12;}} 
}

1 个答案:

答案 0 :(得分:0)

DTO背后的想法是使用虚拟/普通对象进行数据传输,因此您应该避免将复杂性(例如通过继承)添加到此类对象中,否则DTO将失去其简单和序列化友好的主要目的。

关于你的“演员问题”,答案是肯定的,演员将允许使用ThreeIngredientsDto而不是TwoIngredientsDto。

对于私有财产“TheAnswer”,我建议使用const。

总的来说,您的示例尊重SOLID原则,但请注意并非总是我们必须将原始代码中的代码拆分以实现单一责任原则。例如,我不会使用 TwoIngredientsMultiplicationAnswerChecker ThreeIngredientsAdditionAnswerChecker TheAnswerChecker 类,而是使用单个类 TheAnswerChecker 每种类型的DTO的重载方法,这样您的代码将更易读,更容易理解,毕竟,您的课程责任只是检查答案。当然,如果检查每种类型的DTO的答案的逻辑将非常复杂并且需要大量代码,那么可能在不同的类中进行拆分是有意义的。关键是 SOLID 应该代表在构建代码时要记住的一系列原则,但有时打破一些规则可以带来许多好处,在这种情况下你应该做到这一点。< / p>