diff --git a/Directory.Build.props b/Directory.Build.props
index e0900528b67..cddf0d2c372 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -45,7 +45,7 @@
-
+
all
runtime; build; native; contentfiles; analyzers
diff --git a/src/Docfx.Common/Docfx.Common.csproj b/src/Docfx.Common/Docfx.Common.csproj
index d83fc78f609..2d8de76d877 100644
--- a/src/Docfx.Common/Docfx.Common.csproj
+++ b/src/Docfx.Common/Docfx.Common.csproj
@@ -8,6 +8,11 @@
+
+
+
+
+
diff --git a/src/Docfx.Common/EntityMergers/MergePlacement.cs b/src/Docfx.Common/EntityMergers/MergePlacement.cs
new file mode 100644
index 00000000000..44c92c44ad7
--- /dev/null
+++ b/src/Docfx.Common/EntityMergers/MergePlacement.cs
@@ -0,0 +1,33 @@
+// Licensed to the .NET Foundation under one or more agreements.\r
+// The .NET Foundation licenses this file to you under the MIT license.
+
+
+namespace Docfx.Common.EntityMergers;
+
+
+///
+/// The placement for a merge.
+///
+internal enum MergePlacement
+{
+
+ ///
+ /// The placement is not specified.
+ ///
+ None,
+
+ ///
+ /// The override must be placed after the original content.
+ ///
+ After,
+
+ ///
+ /// The override must be placed before the original content.
+ ///
+ Before,
+
+ ///
+ /// The override must replace the original content.
+ ///
+ Replace
+}
diff --git a/src/Docfx.Common/EntityMergers/ReflectionEntityMerger.cs b/src/Docfx.Common/EntityMergers/ReflectionEntityMerger.cs
index 3854d88600b..505d307c55b 100644
--- a/src/Docfx.Common/EntityMergers/ReflectionEntityMerger.cs
+++ b/src/Docfx.Common/EntityMergers/ReflectionEntityMerger.cs
@@ -80,8 +80,55 @@ public void Merge(ref object source, object overrides, IMergeContext context)
{
return;
}
+
+
+ // Gets the placement of the override
+ var placement = MergePlacement.None;
+
+ {
+ if (overrides is IItemWithMetadata ovr
+ && ovr.Metadata.TryGetValue("placement", out var placementValue))
+ {
+ placement =
+ placementValue switch
+ {
+ "after" => MergePlacement.After,
+ "before" => MergePlacement.Before,
+ "replace" => MergePlacement.Replace,
+ _ => MergePlacement.None
+ };
+ }
+ }
+
+
foreach (var prop in Props)
{
+
+ // Placement specified in the override file
+ if (placement != MergePlacement.None
+ && prop.Prop.Name is "Remarks" or "Summary")
+ {
+ var o = prop.Prop.GetValue(overrides);
+
+ if (o is null)
+ continue;
+
+ var s = prop.Prop.GetValue(source);
+
+ s = placement switch
+ {
+ MergePlacement.After => $"{s}{o}",
+ MergePlacement.Before => $"{o}{s}",
+ MergePlacement.Replace => o.ToString()
+ };
+
+ prop.Prop.SetValue(source, s);
+
+ continue;
+ }
+
+
+ // Placement specified in the property
switch (prop.Option)
{
case MergeOption.Merge:
diff --git a/src/Docfx.Common/IItemWithMetadata.cs b/src/Docfx.Common/IItemWithMetadata.cs
new file mode 100644
index 00000000000..8968a3552a8
--- /dev/null
+++ b/src/Docfx.Common/IItemWithMetadata.cs
@@ -0,0 +1,20 @@
+// Licensed to the .NET Foundation under one or more agreements.\r
+// The .NET Foundation licenses this file to you under the MIT license.
+
+
+namespace Docfx.Common;
+
+
+///
+/// An item that contains metadate
+///
+internal interface IItemWithMetadata
+{
+
+ ///
+ /// Gets the metadata.
+ ///
+ /// The metadata.
+ Dictionary Metadata { get; }
+
+}
diff --git a/src/Docfx.Dotnet/ManagedReference/Models/ItemViewModel.cs b/src/Docfx.Dotnet/ManagedReference/Models/ItemViewModel.cs
index dac1880ed40..e740c12868a 100644
--- a/src/Docfx.Dotnet/ManagedReference/Models/ItemViewModel.cs
+++ b/src/Docfx.Dotnet/ManagedReference/Models/ItemViewModel.cs
@@ -13,7 +13,7 @@
namespace Docfx.DataContracts.ManagedReference;
-public class ItemViewModel : IOverwriteDocumentViewModel
+public class ItemViewModel : IOverwriteDocumentViewModel, IItemWithMetadata
{
[YamlMember(Alias = Constants.PropertyName.Uid)]
[JsonProperty(Constants.PropertyName.Uid)]