Skip to content

Guard MarshalByRefObject, [Serializable], and InitializeLifetimeService behind #if NETFRAMEWORK#8174

Open
Evangelink wants to merge 2 commits into
mainfrom
dev/amauryleve/guard-netfx-remoting-artifacts
Open

Guard MarshalByRefObject, [Serializable], and InitializeLifetimeService behind #if NETFRAMEWORK#8174
Evangelink wants to merge 2 commits into
mainfrom
dev/amauryleve/guard-netfx-remoting-artifacts

Conversation

@Evangelink
Copy link
Copy Markdown
Member

Summary

Audit and clean up MarshalByRefObject and [Serializable] usage across src/ to ensure these .NET Framework remoting artifacts are properly scoped to net462 only.

Changes

MarshalByRefObject inheritance (10 classes)

Made all MarshalByRefObject base class inheritance conditional on #if NETFRAMEWORK:

Classes with only MarshalByRefObject as base (6):

  • AssemblyEnumerator, ReflectHelper, RecursiveDirectoryPath, UnitTestRunner, TypeCache, TestAssemblySettingsProvider

Classes implementing MarshalByRefObject + an interface (4):

  • RemotingMessageLogger, NopTraceLogger, EqtTraceLogger, MTPTraceLogger

InitializeLifetimeService overrides (6 methods)

Wrapped all InitializeLifetimeService() overrides (including [SecurityCritical] and the previous [Obsolete] attributes) entirely in #if NETFRAMEWORK. On net462, the override returns null for infinite lifetime. On modern .NET, the override doesn't exist since the base class is no longer MarshalByRefObject.

Also conditionally included using System.Security; to avoid IDE0005 warnings.

[Serializable] attribute (11 non-exception types)

Guarded [Serializable] with #if NETFRAMEWORK on data types that only needed it for BinaryFormatter marshaling across AppDomain boundaries:

  • RecursiveDirectoryPath, UnitTestElement, TestMethod, TestAssemblySettings, StackTraceInformation, MSTestSettings, AssemblyEnumerationResult, TestRunDirectories, DeploymentItem, DeploymentItemOriginType, TestResult

Exception types (AssertFailedException, UnitTestAssertException, etc.) intentionally retain [Serializable] unconditionally — this is a standard .NET convention for exceptions.

Already correctly guarded (no changes needed)

These were already behind #if NETFRAMEWORK:

  • AssemblyLoadWorker, StaticStateHelper (in AppDomainUtilities.cs), AssemblyResolver (conditional base class)
  • All AppDomain.CreateDomain/Unload calls in AppDomainUtilities.cs, AppDomainWrapper.cs, IAppDomain.cs, TestSourceHost.cs

Result

On modern .NET (net8.0/net9.0), these classes are now plain types with no remoting or BinaryFormatter baggage. On net462, the full AppDomain marshaling support is preserved.

Validation

  • dotnet build net9.0 — 0 warnings, 0 errors
  • dotnet build net462 — 0 warnings, 0 errors
  • dotnet build MSTest.TestAdapter net9.0 — 0 warnings, 0 errors
  • dotnet build TestFramework net9.0 — 0 warnings, 0 errors

…ce behind #if NETFRAMEWORK

- Make all MarshalByRefObject inheritance conditional on NETFRAMEWORK across 10 classes
- Wrap InitializeLifetimeService overrides and [SecurityCritical] in #if NETFRAMEWORK
- Guard [Serializable] with #if NETFRAMEWORK on 11 non-exception data types
- Conditionally include 'using System.Security' only for NETFRAMEWORK
- Exception types retain [Serializable] unconditionally (standard .NET convention)

On modern .NET (net8.0/net9.0), these classes are now plain types with no
remoting or BinaryFormatter baggage. On net462, the full AppDomain marshaling
support is preserved.
Copilot AI review requested due to automatic review settings May 13, 2026 10:41
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR scopes .NET Framework remoting/serialization artifacts (MarshalByRefObject, [Serializable], and InitializeLifetimeService) to #if NETFRAMEWORK, keeping AppDomain marshaling behavior on net462 while removing remoting-related baggage from modern .NET builds.

Changes:

  • Guarded MarshalByRefObject inheritance and InitializeLifetimeService() overrides behind #if NETFRAMEWORK.
  • Guarded [Serializable] on non-exception transport/data types behind #if NETFRAMEWORK.
  • Conditionally included using System.Security; only where [SecurityCritical] is compiled to avoid unused-using warnings.
Show a summary per file
File Description
src/TestFramework/TestFramework/Attributes/TestMethod/TestResult.cs Makes TestResult [Serializable] only on .NET Framework.
src/Adapter/MSTestAdapter.PlatformServices/RecursiveDirectoryPath.cs Guards [Serializable], MarshalByRefObject, InitializeLifetimeService, and System.Security usage to .NET Framework.
src/Adapter/MSTestAdapter.PlatformServices/ObjectModel/UnitTestElement.cs Guards [Serializable] to .NET Framework.
src/Adapter/MSTestAdapter.PlatformServices/ObjectModel/TestMethod.cs Guards [Serializable] to .NET Framework.
src/Adapter/MSTestAdapter.PlatformServices/ObjectModel/TestAssemblySettings.cs Guards [Serializable] to .NET Framework.
src/Adapter/MSTestAdapter.PlatformServices/ObjectModel/StackTraceInformation.cs Guards [Serializable] to .NET Framework.
src/Adapter/MSTestAdapter.PlatformServices/NopTraceLogger.cs Makes MarshalByRefObject base conditional for .NET Framework remoting.
src/Adapter/MSTestAdapter.PlatformServices/MSTestSettings.cs Guards [Serializable] to .NET Framework.
src/Adapter/MSTestAdapter.PlatformServices/Helpers/ReflectHelper.cs Makes MarshalByRefObject/InitializeLifetimeService and System.Security usage conditional on .NET Framework.
src/Adapter/MSTestAdapter.PlatformServices/Execution/UnitTestRunner.cs Makes MarshalByRefObject/InitializeLifetimeService and System.Security usage conditional on .NET Framework.
src/Adapter/MSTestAdapter.PlatformServices/Execution/TypeCache.cs Makes MarshalByRefObject/InitializeLifetimeService and System.Security usage conditional on .NET Framework.
src/Adapter/MSTestAdapter.PlatformServices/Execution/TestExecutionManager.cs Makes nested RemotingMessageLogger inherit MarshalByRefObject only on .NET Framework.
src/Adapter/MSTestAdapter.PlatformServices/Execution/TestAssemblySettingsProvider.cs Makes MarshalByRefObject/InitializeLifetimeService and System.Security usage conditional on .NET Framework.
src/Adapter/MSTestAdapter.PlatformServices/Discovery/AssemblyEnumerator.cs Makes MarshalByRefObject/InitializeLifetimeService and System.Security usage conditional on .NET Framework.
src/Adapter/MSTestAdapter.PlatformServices/Discovery/AssemblyEnumerationResult.cs Guards [Serializable] to .NET Framework.
src/Adapter/MSTestAdapter.PlatformServices/Deployment/TestRunDirectories.cs Guards [Serializable] to .NET Framework.
src/Adapter/MSTestAdapter.PlatformServices/Deployment/DeploymentItem.cs Guards [Serializable] on enum and class to .NET Framework.
src/Adapter/MSTest.TestAdapter/VSTestAdapter/EqtTraceLogger.cs Makes MarshalByRefObject base conditional for .NET Framework remoting.
src/Adapter/MSTest.TestAdapter/TestingPlatformAdapter/MTPTraceLogger.cs Makes MarshalByRefObject base conditional for .NET Framework remoting.

Copilot's findings

  • Files reviewed: 19/19 changed files
  • Comments generated: 0

Comment on lines +11 to +13
#if NETFRAMEWORK
[Serializable]
#endif
Copy link
Copy Markdown
Member

@Youssef1313 Youssef1313 May 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider reverting and keep the changes only in Adapter, or at least have this under #if NETFRAMEWORK || NETSTANDARD to be safe. I would be worried if TestFramework netstandard assemblies end up getting loaded in a .NET Framework process where Serializable will be needed.

Under adapter, we no longer target .NET Standard so we are pretty safe there.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually better to simply just revert in this case.

This is a public class and we might not know what users are doing with it.

@Evangelink
Copy link
Copy Markdown
Member Author

@copilot resolve the merge conflicts in this pull request

Co-authored-by: Evangelink <11340282+Evangelink@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI commented May 13, 2026

@copilot resolve the merge conflicts in this pull request

Resolved. The only conflict was in MSTestSettings.cs — the Refactor MSTestSettings into focused partial-class modules commit on main changed class MSTestSettings to partial class MSTestSettings, while this PR had added #if NETFRAMEWORK [Serializable] #endif around it. The resolution combines both: keeping partial and keeping the #if NETFRAMEWORK guard. Merge commit: 41b1475.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants