1

So I'm following through some code snippets for AutoInjector and Automapper online, and noticed something that I don't really understand.

In the code, AutoInjector is Registering Automapper for use in this line.

container.Register(() => config.CreateMapper(container.GetInstance));

I noticed that container.GetInstance isn't having anything passed into it.

After some tinkering, I tried to do var instance = container.GetInstance(); in a console app, but it gives the error The type arguments for method 'Container.GetInstance<TService>() cannot be inferred from the usage. Try specifying the type arguments explicitly.

Obviously, the arguments being passed are inferred from the outer method config.CreateMapper()

I was wondering if there was a way to step through the code so I can see what is being passed into container.GetInstance(). When I step through the code, it just steps over the line and doesn't show me what's being passed into the method.

Jun Kang
  • 1,267
  • 1
  • 10
  • 27

2 Answers2

1

CreateMapper expects as its argument a function which takes an input of Type and returns object.

Func<Type, object>

Looks like container.GetInstance is one such function.


Since you seem to be interested in the internals, here they are:

MapperConfiguration.cs

public IMapper CreateMapper() => new Mapper(this);

Mapper.cs

public Mapper(IConfigurationProvider configurationProvider)
    : this(configurationProvider, configurationProvider.ServiceCtor)
{
}

public Mapper(IConfigurationProvider configurationProvider, Func<Type, object> serviceCtor)
{
    _configurationProvider = configurationProvider;
    _serviceCtor = serviceCtor;
    DefaultContext = new ResolutionContext(new ObjectMappingOperationOptions(serviceCtor), this);
}
Mateen Ulhaq
  • 24,552
  • 19
  • 101
  • 135
  • Yeah, it is, and I understand that much. But is there a way to step through the a specific usage of the code, and see what is being passed as the argument? – Jun Kang Jul 05 '17 at 22:35
  • You can look through the source code for Automapper. This is an external library and the only way to look at what's going inside is through a disassembler or the source code itself. – Mateen Ulhaq Jul 05 '17 at 22:36
  • *“My guess is that Type is likely a generic”* – Given that you’ve now made the effort to look at the source code, you can remove that guess. There is nothing generic about the method. – poke Jul 06 '17 at 07:31
1

I noticed that container.GetInstance isn't having anything passed into it.

Because nothing is. The argument of CreateMapper is a delegate, more specifically a Func<Type, object>; So config.CreateMapper(container.GetInstance) is exactly the same as if you'd written:

config.CreateMapper(type => GetInstance(type));

You are not passing in any concrete arguments at that point in time, you are simply "informing" container how to create a mapper for any given type,

Its the same as the following LINQ usage in this trivial code snippet (hence the possible duplicate comment):

public static string ToString<T>(T arg) => arg.ToString();

var ints = Enumerable.Empty<int>();
var strs = ints.Select(ToString); //or ints.Select(i => ToString(i))

What arguments are passed into ToString in the Select call? Well, none, you are only informing Select how to map an int to a string, you are not processing any integers yet (you wouldn't be able to anyways, the enumeration is empty!). The arguments will be passed into the delegate (or not) when the enumeration is enumerated.

Your code is the same, an argument typed Type (if any) will be passed into GetInstance whenever a mapper needs to be created for any given type. The code you've posted is irrelevant as to when and for what specific type that happens, thats why while debugging you simply step over that line.

InBetween
  • 32,319
  • 3
  • 50
  • 90