Not sure if this is a supported use case for ExpressMapper, but it seems like a common pattern to perform one time actions in static constructors. With regard to dto mapping, it seems especially convenient to register mappings in a static constructor of the dto class.
Is ExpressMapper meant to support this use case?
I have found that this approach causes issues with ExpressMapper in that it throws "already registered" exceptions for specific cases. This seems to stem from the fact that the no reference to the dto type has been made yet (thus the static constructor is not called), so it will be a cache miss inside Map<T, TN>(). Then, later on, when default(T/TN) is called, the static constructor is invoked (calling Register and putting it into the cache at this point). But by this time the code path is already determined and it will proceed to RegisterInternal where the mapping is in the cache and thus the exception gets thrown.
Repro:
static void GetDto() {
var persons = new List<Person>();
// var bleh = new PersonDto(); // <--uncommenting this will not throw exception
var test = persons.Map<IEnumerable<Person>, IEnumerable<PersonDto>>();
public class Person {
}
public class PersonDto {
static PersonDto() {
Mapper.Register<Person, PersonDto>();
}
}
}
Not sure if this is a supported use case for ExpressMapper, but it seems like a common pattern to perform one time actions in static constructors. With regard to dto mapping, it seems especially convenient to register mappings in a static constructor of the dto class.
Is ExpressMapper meant to support this use case?
I have found that this approach causes issues with ExpressMapper in that it throws "already registered" exceptions for specific cases. This seems to stem from the fact that the no reference to the dto type has been made yet (thus the static constructor is not called), so it will be a cache miss inside Map<T, TN>(). Then, later on, when default(T/TN) is called, the static constructor is invoked (calling Register and putting it into the cache at this point). But by this time the code path is already determined and it will proceed to RegisterInternal where the mapping is in the cache and thus the exception gets thrown.
Repro: