diff --git a/nuget/Microsoft.Windows.CsWinRT.targets b/nuget/Microsoft.Windows.CsWinRT.targets
index 0966cfc4c..dbb87848f 100644
--- a/nuget/Microsoft.Windows.CsWinRT.targets
+++ b/nuget/Microsoft.Windows.CsWinRT.targets
@@ -567,6 +567,7 @@ $(CsWinRTInternalProjection)
true
true
false
+ false
+
diff --git a/nuget/readme.md b/nuget/readme.md
index 78d04bec7..cc027eca6 100644
--- a/nuget/readme.md
+++ b/nuget/readme.md
@@ -78,6 +78,7 @@ C#/WinRT supports several feature switches to opt-out of some features available
| CsWinRTEnableICustomPropertyProviderSupport | \*true \| false | Enables marshalling of `ICustomPropertyProvider` objects. Setting this to **false** allows trimming all supporting code for this interface, and will make it not available on marshalled CCW types. |
| CsWinRTEnableIReferenceSupport | \*true \| false | Enables support and marshalling of `IReference`, `IReferenceArray` and `IPropertyValue` objects. Setting this to **false** allows trimming all supporting code for all three interfaces, and will make all of them not available on marshalled CCW types. |
| CsWinRTEnableIDynamicInterfaceCastableSupport | \*true \| false | Enables support for the [`IDynamicInterfaceCastable`](https://devblogs.microsoft.com/dotnet/improvements-in-native-code-interop-in-net-5-0/#idynamicinterfacecastable) infrastructure for RCW types. Setting this to **false** allows trimming of all related code, and will disallow casting RCW types to interface types they don't directly implement in metadata. |
+| CsWinRTLoadComponentsInDefaultALC | true \| \*false | Setting this to **true** configures `WinRT.Host.dll` to load CsWinRT components in the default [`Assembly Load Context (ALC)`](https://learn.microsoft.com/dotnet/core/dependency-loading/understanding-assemblyloadcontext). Note you should ensure components and dependencies loaded are compatible and will not conflict in any way to avoid potential issues. By default, when set to **false**, they load in their own ALC. |
\*Default value
### Windows Metadata
diff --git a/src/Authoring/WinRT.Host.Shim/Module.cs b/src/Authoring/WinRT.Host.Shim/Module.cs
index bb90a0b3b..a896b1c37 100644
--- a/src/Authoring/WinRT.Host.Shim/Module.cs
+++ b/src/Authoring/WinRT.Host.Shim/Module.cs
@@ -3,10 +3,12 @@
using System;
using System.Collections.Concurrent;
+using System.Collections.Generic;
using System.Reflection;
#if NET
using System.Runtime.Loader;
+using System.Threading;
[assembly: global::System.Runtime.Versioning.SupportedOSPlatform("Windows")]
#endif
@@ -21,6 +23,52 @@ public static class Shim
public unsafe delegate int GetActivationFactoryDelegate(IntPtr hstrTargetAssembly, IntPtr hstrRuntimeClassId, IntPtr* activationFactory);
+#if NET
+ private const string UseLoadComponentsInDefaultALCPropertyName = "CSWINRT_LOAD_COMPONENTS_IN_DEFAULT_ALC";
+ private readonly static bool _IsLoadInDefaultContext = IsLoadInDefaultContext();
+
+ private static HashSet _InitializedResolversInDefaultContext = null;
+
+ public static Assembly LoadInDefaultContext(string targetAssembly)
+ {
+ if (_InitializedResolversInDefaultContext == null)
+ {
+ Interlocked.CompareExchange(ref _InitializedResolversInDefaultContext, new HashSet(StringComparer.OrdinalIgnoreCase), null);
+ }
+
+ lock (_InitializedResolversInDefaultContext)
+ {
+ if (!_InitializedResolversInDefaultContext.Contains(targetAssembly))
+ {
+ var resolver = new AssemblyDependencyResolver(targetAssembly);
+ AssemblyLoadContext.Default.Resolving += (AssemblyLoadContext assemblyLoadContext, AssemblyName assemblyName) =>
+ {
+ string assemblyPath = resolver.ResolveAssemblyToPath(assemblyName);
+ if (assemblyPath != null)
+ {
+ return assemblyLoadContext.LoadFromAssemblyPath(assemblyPath);
+ }
+ return null;
+ };
+
+ _InitializedResolversInDefaultContext.Add(targetAssembly);
+ }
+ }
+
+ return AssemblyLoadContext.Default.LoadFromAssemblyPath(targetAssembly);
+ }
+
+ public static bool IsLoadInDefaultContext()
+ {
+ if (AppContext.TryGetSwitch(UseLoadComponentsInDefaultALCPropertyName, out bool isEnabled))
+ {
+ return isEnabled;
+ }
+
+ return false;
+ }
+#endif
+
public static unsafe int GetActivationFactory(IntPtr hstrTargetAssembly, IntPtr hstrRuntimeClassId, IntPtr* activationFactory)
{
*activationFactory = IntPtr.Zero;
@@ -30,7 +78,19 @@ public static unsafe int GetActivationFactory(IntPtr hstrTargetAssembly, IntPtr
try
{
+#if NET
+ Assembly assembly;
+ if (_IsLoadInDefaultContext)
+ {
+ assembly = LoadInDefaultContext(targetAssembly);
+ }
+ else
+ {
+ assembly = ActivationLoader.LoadAssembly(targetAssembly);
+ }
+#else
var assembly = ActivationLoader.LoadAssembly(targetAssembly);
+#endif
var type = assembly.GetType("WinRT.Module");
if (type == null)
{