2016-01-21 87 views
0

我提到過我沒有用DTO的很多東西。我在DataTransfereObjects上玩弄polimophism。我找不到一個很好的解決方案,所以我已經使這個代碼示例掌握了DataTransfereObjects和不同邏輯實現的多態性,使用Polymorphism,泛型,接口,抽象等等。掌握dto多態性

請檢查驗證碼。告訴我什麼是壞的,可以做得更好或更容易。檢查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;}} 
} 

回答

0

背後的DTO的想法是使用虛擬/普通對象進行數據傳輸,因此,你應該避免通過繼承增加複雜性,例如,這種類型的對象,否則的DTO將失去的是簡單他們的主要目的和序列化友好。

關於你的「演員問題」,答案是肯定的,演員將允許使用ThreeIngredientsDto而不是TwoIngredientsDto。

對於私人財產「TheAnswer」,我會建議使用const。

總體而言,您的示例尊重SOLID原則,但請注意,並非總是必須將原子代碼中的代碼拆分以實現單一責任原則。例如,而不是具有TwoIngredientsMultiplicationAnswerCheckerThreeIngredientsAdditionAnswerCheckerTheAnswerChecker類,我會用一個單一的類TheAnswerChecker這將對每種類型DTO的過載的方法,在這種方式的代碼將是更好的可讀性和更可以理解,畢竟,你的課堂責任只是檢查答案。當然,如果爲每種類型的DTO檢查答案的邏輯將非常複雜並且需要大量的代碼,那麼在不同的類中進行拆分可能是有意義的。關鍵是,SOLID應該代表一組要在構建代碼時記住的原則,但有時違反一些規則可能會帶來很多好處,在這種情況下,您應該做出妥協。