C# 掌握dto同态

C# 掌握dto同态,c#,generics,polymorphism,dto,solid-principles,C#,Generics,Polymorphism,Dto,Solid Principles,我提到我和DTO的合作不多。我在玩数据对象上的polimophism。我想不出一个好的解决方案,所以我制作了这个代码示例来掌握带有DataTransferObject和不同逻辑实现的polimorphism,使用polimorphism、泛型、接口、抽象等等 请检查代码。提示我什么不好,可以做得更好或更容易。检查accessmodifier,也检查SOLID(我想我没有正确理解它)。最后,它似乎太复杂了,用这种方式解决它是常见的吗 实际上,我尝试调用一些(反)序列化的编程逻辑,它对派生的DTO使

我提到我和DTO的合作不多。我在玩数据对象上的polimophism。我想不出一个好的解决方案,所以我制作了这个代码示例来掌握带有DataTransferObject和不同逻辑实现的polimorphism,使用polimorphism、泛型、接口、抽象等等

请检查代码。提示我什么不好,可以做得更好或更容易。检查accessmodifier,也检查SOLID(我想我没有正确理解它)。最后,它似乎太复杂了,用这种方式解决它是常见的吗

实际上,我尝试调用一些(反)序列化的编程逻辑,它对派生的DTO使用baseDto,而不会丢失它们的特定信息。这段代码应该是解决这类问题的干净的抽象沙箱

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;}} 
}
void Main()
{
var twoIngrDto=new TwoIngredientsDto();
var threeIngrDto=新的ThreeIngredientsDto();
var twoIngrMulAnswerChecker=新的TwoIngredientsMultiplicationAnswerChecker();
var threeingradanswerchecker=新的ThreeIngredientsAdditionAnswerChecker();
twoIngrMulAnswerChecker.IsTheAnswerCheckImplementationTheAnswer(twoIngrDto);//TRUE.Dump();
ThreeingAddAnswerChecker.IsTheAnswerCheckImplementationTheAnswer(threeIngrDto);//TRUE.Dump();
twoIngrMulAnswerChecker.IsTheAnswerCheckImplementationTheAnswer(threeIngrDto);//FALSE.Dump();
IAnswerCheck answerchecker=new IngredientsAnswerChecker();
checkAnswerChecker.checkAnswerChecker(twoIngrMulAnswerChecker,twoIngrDto);//TRUE.Dump();
checkAnswerChecker.CheckAnswer(ThreeingradanswerChecker,threeIngrDto);//TRUE.Dump();
///问题:如何将应答检查器“twoIngrMulAnswerChecker”与派生的DTO“threeIngrDto”一起使用
///它失败,出现以下错误:
///“UserQuery.TwoingCreditsMultiplicationAnswerChecker”类型不能用作
///在泛型类型或方法“UserQuery.IngredientsAnswerChecker.CheckAnswer(T,DTO)”中键入参数“T”。
///“UserQuery.TwoingCreditsMultiplicationAnswerChecker”中没有隐式引用转换
///到“UserQuery.TheAnswerChecker”。
//checkAnswerChecker.checkAnswerChecker(两个rmulanswerChecker,三个rdto).Dump();
answerchecker.checkAnswerChecker(twoIngrMulAnswerChecker,(TwoingCreditsTo)ThreeingrTo.Dump();//正在强制转换解决方案吗?
}
接口IAnswerCheck
{
bool CheckAnswer(T answercker,DTO IngreditsDTO)
其中T:TheAnswerChecker
式中,DTO:IngreditDTO;
}
公共抽象类回答检查器,其中T:IngreedintDTO
{
回答检查实施中的内部摘要(T回答REDIETSDTO);
私有int回答{get{return 42;}
公共布尔值是回答检查实施回答(T回答REDIETSDTO)
{
返回answer==answercheck实现(answerIngredietsDto);
}
}
//生成基类
公共类InCreditsAnswerChecker:IAnswerCheck/:AnswerChecker
{
公共bool CheckAnswer(T answercker,DTO IngreditsDTO)
其中T:TheAnswerChecker
其中DTO:IngreditDTO
{
返回应答器。是否执行应答器检查应答器(InCreditsDTO);
}
}
公共第二类用户多应用应答器检查器:应答器检查器
{
answercheckimplementation(TwoingReditesTo answeringReditesTo)中的内部重写//其中T:TwoingReditesTo
{ 
返回answeringreditesdto.A*answeringreditesdto.B;
}
}
公共三级信用证应答人:应答人
{
应答器检查实施中的内部覆盖(三重应答器应答器应答器)
{
返回answerIngredietsDto.A+answerIngredietsDto.B+answerIngredietsDto.C;
}
}
公共类IngredientDto
{
公共信贷机构()
{
Id=Guid.NewGuid();
}
公共Guid Id{get;private set;}
}
公共类2 INGREDIENTSDTO:IngredientDto
{
公共虚拟int A{get{return 6;}}
公共虚拟int B{get{return 7;}}
}
公共类三元信用证收件人:二元信用证收件人
{
公共重写int B{get{return 24;}}
公共int C{get{return 12;}}
}

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

关于您的“cast问题”,答案是肯定的,cast将允许使用三个REDIENTSDTO而不是两个REDIENTSDTO

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

总的来说,您的示例尊重可靠的原则,但请注意,为了实现单一责任原则,我们不必总是将代码分成原子部分。例如,我将使用一个类AnswerChecker,该类将为每种类型的DTO提供重载方法,而不是使用两个多应用AnswerChecker三个多应用AnswerCheckerAnswerChecker类,通过这种方式,您的代码将更具可读性和可理解性,毕竟,您的类责任将只是检查答案。当然,如果检查每种类型DTO的答案的逻辑非常复杂,并且需要大量代码,那么将其划分为不同的类可能是有意义的。要点是,SOLID应该代表一组在构建代码时要牢记的原则,但有时违反一些规则会带来很多好处,在这种情况下,您应该做这种折衷