Skip to content

Re-evaluate the AutoMapper.Internal surface #4656

Description

@jbogard

The AutoMapper.Internal namespace and the .Internal() escape hatches (InternalApi, IGlobalConfiguration, IGlobalConfigurationExpression, IProfileExpressionInternal, and the ~41 [EditorBrowsable(Never)] members alongside them) were introduced to shrink the discoverable public surface, on the theory that fewer visible knobs means fewer edge-case issues to triage.

Worth re-examining whether that has actually paid off, because the cost side is now visible.

Why now

#4655 turned up a concrete example. The only way to express blanket "ignore null source values" PATCH semantics today is:

cfg.Internal().ForAllPropertyMaps(pm => pm.SourceMember != null, (pm, opt) =>
{
    var member = pm.SourceMember;
    opt.PreCondition((object src) => ((PropertyInfo)member).GetValue(src) != null);
});

That works — I verified it. But it lives on IProfileExpressionInternal, is hidden from IntelliSense, and appears nowhere in the docs. Five issues over eight years (#2918, #2999, #3926, #4530, #4627) asked for exactly this behavior and none of them surfaced it. So in that instance hiding the API did not prevent the issues; it just meant nobody could find the answer, and the issues kept arriving anyway.

Questions to answer

  • Did issue volume actually drop after the Internal split, or did the same questions keep coming in a different shape?
  • Which Internal members are genuinely implementation detail (subject to change without notice) versus supported-but-advanced? Those are two different things currently sharing one namespace and one [EditorBrowsable(Never)] marker.
  • For the supported-but-advanced set: promote to the public surface, document, and accept the triage cost — or keep hidden but document, so the answer is at least findable from a search?
  • Does [EditorBrowsable(Never)] carry its weight, given it hides from IntelliSense but not from source, samples, or Stack Overflow answers?
  • What is the ApiCompat/versioning story if members move between the two? Anything promoted out of Internal becomes a compatibility commitment.

ForAllPropertyMaps is the first concrete candidate for promotion, but the point of this issue is the policy, not that one member.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions