agileobjects / AgileMapper

A zero-configuration, highly-configurable, unopinionated object mapper with viewable execution plans. Flattens, unflattens, deep clones, merges, updates and projects queries. .NET 3.5+ and .NET Standard 1.0+.
MIT License
460 stars 27 forks source link

Error when mapping with injected service #204

Closed jornhd closed 4 years ago

jornhd commented 4 years ago

AgileMapper Version 1.7.1 I'm having problems when trying to use an injected service in member mapping. Using .NET core 3.1, I've setup the service provider in public static void Configure(IApplicationBuilder app):

            Mapper.WhenMapping
                .UseServiceProvider(app.ApplicationServices);

This seems to work fine as I get a logger message in mapping configuration:

    public class MyDtoMapper : MapperConfiguration
    {
        protected override void Configure()
        {
            GetService<ILogger<MyDtoMapper>>().LogInformation("Hello, from MyDtoMapper");
            WhenMapping....
        }
    }

I've tried this from the documentation:

A value from an injected service:

// Retrieve an IDateTimeProvider instance from a configured
// service provider, and use its UtcNow value:
Mapper.WhenMapping
    .From<OrderDto>()        // Apply to OrderDto mappings
    .ToANew<Order>()         // Apply to Order creation
    .Map(ctx => ctx.GetService<IDateTimeProvider>().UtcNow)
    .To(o => o.DateCreated); // o is the Order

But this results in the following exception.

System.InvalidOperationException: variable 'i' of type 'System.Int32' referenced from scope '', but it is not defined at System.Linq.Expressions.Compiler.VariableBinder.Reference(ParameterExpression node, VariableStorageKind storage)

So.. I'm I doing something wrong, or is this a bug?

SteveWilkes commented 4 years ago

That sounds like a bug - I'll check it out. Thanks for letting me know!

Steve

SteveWilkes commented 4 years ago

Hi!

I've had a go and been unable to reproduce this - here's a fiddle which successfully maps using GetService<>.

Could you share exactly what you're trying to map, please?

All the best,

Steve

jornhd commented 4 years ago

Modified your fiddle, and now get the same error: https://dotnetfiddle.net/4XzT0u

SteveWilkes commented 4 years ago

I've had a look into this, and while I haven't yet figured out the error you're getting (which I'll find and sort out, cos I at least want it to fail gracefully), there is an issues with what you're trying to do.

Query Projection creates a mapping expression which is transformed by an underlying QueryProvider - EntityFramework, for example - into SQL. Because the mapping is applied via the QueryProvider, AgileMapper only applies configurations which can be supported in SQL - values obtained from injected services would not be supported, and configurations setting those up will be ignored in projections.

SteveWilkes commented 4 years ago

This is fixed in the current 1.7.2 release branch - injected service values are now filtered out of query projections.

Thanks again for letting me know!

SteveWilkes commented 4 years ago

This is fixed in release 1.7.2, which is now on NuGet.

Thanks again!