NServiceBus.Persistence.Sql icon indicating copy to clipboard operation
NServiceBus.Persistence.Sql copied to clipboard

Saga script generation fails if message mapping maps to a field

Open DavidBoike opened this issue 4 years ago • 0 comments

Saga script generation will fail on this saga:

public class MySaga : Saga<MyData>,
    IAmStartedByMessages<Msg>
{
    protected override void ConfigureHowToFindSaga(SagaPropertyMapper<MyData> mapper)
    {
        mapper.ConfigureMapping<Msg>(msg => msg.CorrId).ToSaga(saga => saga.ScriptRunId);
    }

    public Task Handle(Msg message, IMessageHandlerContext context) => throw new NotImplementedException();
}

public class MyData : ContainSagaData
{
    public Guid ScriptRunId { get; set; }
}

public class Msg : ICommand
{
    public Guid CorrId;
}

The cause is that Msg.CorrId is a field, and not a property.

A property would generate the following IL:

IL_000C:  ldstr       "msg"
IL_0011:  call        System.Linq.Expressions.Expression.Parameter
IL_0016:  stloc.0     
IL_0017:  ldloc.0     
IL_0018:  ldtoken     UserQuery+Msg.get_CorrId
IL_001D:  call        System.Reflection.MethodBase.GetMethodFromHandle
IL_0022:  castclass   System.Reflection.MethodInfo
IL_0027:  call        System.Linq.Expressions.Expression.Property

While with a field, it generates:

IL_000C:  ldstr       "msg"
IL_0011:  call        System.Linq.Expressions.Expression.Parameter
IL_0016:  stloc.0     
IL_0017:  ldloc.0     
IL_0018:  ldtoken     UserQuery+Msg.CorrId
IL_001D:  call        System.Reflection.FieldInfo.GetFieldFromHandle
IL_0022:  call        System.Linq.Expressions.Expression.Field

The last 2 call instances for the field are not included on the list of allowed calls so the instruction analyzer assumes that the user is calling out to a separate method, and if the mapper were passed to that method, all sorts of extra mapping could be going on behind the back of the instruction analyzer which can only look at the IL for the one method.

Whether or not fields are appropriate for messages matters more on the choice of serializer than anything else. The saga script generator shouldn't fail because of it.

Workaround

Don't use fields in messages.

DavidBoike avatar Mar 17 '21 16:03 DavidBoike