I now have about this code:

public override Expression<Func<ITask, TaskDto>> ConvertEntityToDto() { return t => t.TypeDiscriminator == guid ? new SimpleTaskDto((ISimpleTask)t) : new TaskDto(t); } 

It works fine, sometimes it returns me SimpleTaskDto , sometimes TaskDto , everything is as planned.

In fact, I want to do a little harder - return the FooTaskDto fooGuid-FooTaskDto pairs that are known in the runtime, and the TaskDto to the unknown TaskDto .

Can this be built through Expression? If not, what options are there?

The bottom line is that this is part of transforming entities from the database into Dto, and if I choose the wrong type, then I lose some useful fields, which makes it necessary to make a separate query, although I could do it right here.

  • Hmm, is t.TypeDiscriminator known statically? Well, you do not want to lookup then hold it at the base level? - VladD
  • (Or are you not for databases? Then why not lookup directly in the text of expression?) - VladD
  • @VladD is better than a separate request later. Those. lookup will suit me. - Monk
  • So for the base, but I'm honestly stupid, but how else can you get along with the request. - Monk
  • Okay, why not just t => (t.TypeDiscriminator == guid1) ? new SimpleTaskDto((ISimpleTask)t) : (t.TypeDiscriminator == guid2) ? new FooTaskDto((IFooTask)t) : new TaskDto(t) t => (t.TypeDiscriminator == guid1) ? new SimpleTaskDto((ISimpleTask)t) : (t.TypeDiscriminator == guid2) ? new FooTaskDto((IFooTask)t) : new TaskDto(t) t => (t.TypeDiscriminator == guid1) ? new SimpleTaskDto((ISimpleTask)t) : (t.TypeDiscriminator == guid2) ? new FooTaskDto((IFooTask)t) : new TaskDto(t) ? - VladD

1 answer 1

See it. You can build the same thing manually, and add conditions iteratively.

Let's write an analogue of such an expression:

 t => t.TypeDiscriminator == guid1 ? new SimpleTaskDto((ISimpleTask)t) : t.TypeDiscriminator == guid2 ? new FooTaskDto((IFooTask)t) : // Ρ‚ΡƒΡ‚ Π΅Ρ‰Ρ‘ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ... new TaskDto(t); 

Here is an example:

 var parameter = Expression.Parameter(typeof(ITask), "t"); // new TaskDto(t) Expression result = Expression.New(typeof(TaskDto).GetConstructor(new[] { typeof(ITask) }), parameter); // t.TypeDiscriminator var typeDiscr = Expression.Property(parameter, "TypeDiscriminator"); // эта Ρ‡Π°ΡΡ‚ΡŒ Π΄ΠΎΠ»ΠΆΠ½Π° Π±Ρ‹Ρ‚ΡŒ Π² Ρ†ΠΈΠΊΠ»Π΅ ΠΏΠΎ Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹ΠΌ ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½Ρ‹ΠΌ Ρ‚ΠΈΠΏΠ°ΠΌ // ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹ ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½ΠΎΠΉ ΠΈΡ‚Π΅Ρ€Π°Ρ†ΠΈΠΈ Ρ†ΠΈΠΊΠ»Π° Guid guid = guid1; Type parameterType = typeof(ISimpleTask); Type dtoType = typeof(SimpleTaskDto); // t.TypeDiscriminator == guid1 var test = Expression.Equal(typeDiscr, Expression.Constant(guid)); // (ISimpleTask)t var parameterCasted = Expression.Convert(parameter, parameterType); // (TaskDto)new SimpleTaskDto((ISimpleTask)t) // каст Π½ΡƒΠΆΠ΅Π½, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΎΠ±Π΅ части ΠΈΠΌΠ΅Π»ΠΈ ΠΎΠ±Ρ‰ΠΈΠΉ Ρ‚ΠΈΠΏ var altResult = Expression.Convert( Expression.New(dtoType.GetConstructor(new[] { parameterType }), parameterCasted), typeof(TaskDto)); // Π°ΠΊΠΊΡƒΠΌΡƒΠ»ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹ΠΉ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ result = Expression.Condition(test: test, ifTrue: altResult, ifFalse: result); // ΠΊΠΎΠ½Π΅Ρ† Ρ†ΠΈΠΊΠ»Π° Ρ‚ΡƒΡ‚ // собираСм всё Π² лямбду: return Expression.Lambda<Func<ITask, TaskDto>>(result, parameter); 
  • I first read this code from the bottom up, otherwise it's easy to get confused. - AK ♦
  • @AK: I would pack everything into one expression, and it would fit well with the tree. But in this case it is impossible to give "speaking" names of temporary variables. - VladD
  • Expression.Condition issued a 'System.ArgumentException' with the text - The argument types do not match. The variables are the constructors SimpleTaskDto and TaskDto. They need to somehow bring? This is how my code looks right now, which correctly collects dto chains - gist.github.com/MonkAlex/53f6b018a759c2fbd5d98a3917186b01 - Monk
  • Ok, updated gist, I added the conversion to the base type and then it runs successfully and visually gives quite the right result. If possible, I would have a hint, everything is fine with me now, or did I miss something or did it wrong? - Monk
  • @Monk: I'll see what's wrong when I get to the computer ... - VladD