Scenario
Assume we have a class Target with the following two constructors (one objec, or two objects and an Enum).
public Target(paramOne) { ... }
public Target(paramOne, paramTwo, paramTwoConfigEnum) { ... }
We then have a ClassA which needs to perform a mapping operation from some object to an instance of Target. One version of this would be the following, which relies on existign mapping rules (for automapper), and dependency injection using AutoFac for providing the parameters to perform the mapping. This uses the last of the two constructors above (3 params):
// Behind the scenes this performs a call like: new Target(p1, p2, myEnum)
// with p1, p2 and
var result = _mapper.Map<List<Target>>(someOtherObject);
Next, we have two other classes ClassB, and ClassC. Both of these need to perform similar mapping operations, but here the resulting objects are classes that contain instances of Target; in other words, there is an behind-the-scenes, implicit mapping from someOtherObject into Target here too:
// Behind the scenes this performs calls conceptually similar to the following
// (NB: The second line here will call new Target() with 3 params, as above):
// var x = new ClassContainingTarget(..)
// x.instOfTarget = _mapper.Map<List<Target>>(someOtherObject);
var result = _mapper.Map<ClassContainingTarget>(anotherSourceObject);
The first challenge
For ClassB, the call operation requires values for all three parameters to Target, and values are provided for these via DI.
For ClassC however, paramTwo and paramTwoConfigEnum are not only not needed; they can't be provided via DI in this context. In other words, I what I would like to happen is for the other constructor in Target to be called in this case.
Attempted solution
I realized I can specify which constructor to use when setting up the rules for AutoFac, and override these in specific cases, so I've experimented with the following general setup in my ContainerBuilder:
// This specifies that the constructor that takes a single param of type ParamOne
// should be used by default:
builder.RegisterType<Target>().AsSelf().UsingConstructor(typeof(ParamOne));
With this setup, all the Map() calls above will result in the second (single-param) constructor of Target being used, including in the case of ClassC, where that is exactly what I want.
For the mapping in ClassA then, I can override this logic by replacing the Map() operation shown above with the following:
// Direct manipulation of the rules for mapping to Target, since I'm
// mapping directly to Target. As mentioned below, this does not appear
// to be possible when mapping to classes that contain Target (i.e.
// when Target is mapped implicitly).
result = _mapper.Map<List<Target>>(
someOtherObject,
options =>
options.ConstructServicesUsing(t => new Target(_p1, _p2, myEnum)));
This actualy works in part: Mapping in ClassA causes the 3-param constructor to be called, while that in ClassC causes the 1-param constructor to be called.
Remaining problem
Now the problem remains with ClassB however: I can't see any way to configure it such that it will call the 3-param constructor for Target, since that instantiation and mapping is defined at a lower level, so to speak.
So my question then: Is there any way for me to specify (either from ClassB, or somewhere else) that when Target is instantiated from ClassB, it should use some specific constructor?
Or alternatively, is there some better strategy to get around this problem?