Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions nuget/Microsoft.Windows.CsWinRT.targets
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,7 @@ $(CsWinRTInternalProjection)
<CsWinRTEnableIDynamicInterfaceCastableSupport Condition="'$(CsWinRTEnableIDynamicInterfaceCastableSupport)' == ''">true</CsWinRTEnableIDynamicInterfaceCastableSupport>
<CsWinRTEnableManifestFreeActivation Condition="'$(CsWinRTEnableManifestFreeActivation)' == ''">true</CsWinRTEnableManifestFreeActivation>
<CsWinRTManifestFreeActivationReportOriginalException Condition="'$(CsWinRTManifestFreeActivationReportOriginalException)' == ''">false</CsWinRTManifestFreeActivationReportOriginalException>
<CsWinRTLoadComponentsInDefaultALC Condition="'$(CsWinRTLoadComponentsInDefaultALC)' == ''">false</CsWinRTLoadComponentsInDefaultALC>

<!--
Note: the 'CsWinRTUseWindowsUIXamlProjections' property and associated 'CSWINRT_USE_WINDOWS_UI_XAML_PROJECTIONS' feature
Expand Down Expand Up @@ -619,6 +620,11 @@ $(CsWinRTInternalProjection)
<RuntimeHostConfigurationOption Include="CSWINRT_MANIFEST_FREE_ACTIVATION_REPORT_ORIGINAL_EXCEPTION"
Value="$(CsWinRTManifestFreeActivationReportOriginalException)"
Trim="true" />

<!-- CSWINRT_LOAD_COMPONENTS_IN_DEFAULT_ALC switch -->
<RuntimeHostConfigurationOption Include="CSWINRT_LOAD_COMPONENTS_IN_DEFAULT_ALC"
Value="$(CsWinRTLoadComponentsInDefaultALC)"
Trim="true" />
</ItemGroup>

</Project>
1 change: 1 addition & 0 deletions nuget/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -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<T>`, `IReferenceArray<T>` 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
Expand Down
60 changes: 60 additions & 0 deletions src/Authoring/WinRT.Host.Shim/Module.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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<string> _InitializedResolversInDefaultContext = null;

public static Assembly LoadInDefaultContext(string targetAssembly)
{
if (_InitializedResolversInDefaultContext == null)
{
Interlocked.CompareExchange(ref _InitializedResolversInDefaultContext, new HashSet<string>(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;
Expand All @@ -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)
{
Expand Down
Loading