0

The .NET 7 docs provide an example on how to use the MarshalByRefObject class to create class instances in secondary domains. I replicated this example almost identically as follows:

using System;
using System.Reflection;

namespace MarshalByRefObjectExample 
{
    public class Worker : MarshalByRefObject
    {
        public void PrintDomain()
        {
            Console.WriteLine("Object is executing in AppDomain \"{0}\"",
                AppDomain.CurrentDomain.FriendlyName);
        }
    }

    internal class Program
    {
        static void Main(string[] args)
        {      
            // Create an ordinary instance in the current AppDomain
            Worker localWorker = new Worker();
            localWorker.PrintDomain();

            // Create a new AppDomain, an instance of Worker and execute code in there
            AppDomain ad = AppDomain.CreateDomain("New domain");
            Worker remoteWorker = (Worker) ad.CreateInstanceAndUnwrap(
                typeof(Worker).Assembly.FullName,
                "Worker"
            );

            remoteWorker.PrintDomain();       
        }
    }
}

When I run this example, I get an error as follows:

Object is executing in AppDomain "MarshalByRefObjectExample"

Unhandled exception. System.PlatformNotSupportedException: Secondary AppDomains are not supported on this platform.

at System.AppDomain.CreateDomain(String friendlyName)

at MarshalByRefObjectExample.Program.Main(String[] args) in Program.cs:line 24

My project file looks like the following:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net7.0</TargetFramework>
    <RootNamespace>MarshalByRefObjectExample</RootNamespace>
    <Nullable>enable</Nullable>
  </PropertyGroup>
</Project>

What am I doing wrong here?

Edit

After reading some of the comments, I tried redefining my project to use the .NET Framework instead of .NET Core as follows:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net472</TargetFramework>
    <RootNamespace>MarshalByRefObjectExample</RootNamespace>
  </PropertyGroup>

</Project>

I'm getting a different error now:

Unhandled Exception: System.TypeLoadException: Could not load type 'Worker' from assembly 'MarshalByRefObjectExample, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.

at System.Reflection.RuntimeAssembly.GetType(RuntimeAssembly assembly, String name, Boolean throwOnError, Boolean ignoreCase, ObjectHandleOnStack type)

at System.Reflection.RuntimeAssembly.GetType(String name, Boolean throwOnError, Boolean ignoreCase)

at System.Activator.CreateInstance(String assemblyString, String typeName, Boolean ignoreCase, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes, Evidence securityInfo, StackCrawlMark& stackMark)

at System.Activator.CreateInstance(String assemblyName, String typeName)

at System.AppDomain.CreateInstance(String assemblyName, String typeName) at System.AppDomain.CreateInstanceAndUnwrap(String assemblyName, String typeName) at System.AppDomain.CreateInstanceAndUnwrap(String assemblyName, String typeName) at MarshalByRefObjectExample.Program.Main(String[] args) in Program.cs:line 25

user32882
  • 5,094
  • 5
  • 43
  • 82
  • What do you want to achieve with `AppDomain`s? Creating new domains works only if you target .NET Framework, but this feature has been removed from .NET Core. It was used mainly for remoting or making possible to unload assemblies (eg. when unloading plugins in an extensible application). But remoting has also been removed in .NET Core, whereas to unload assemblies you can use the `AssemblyLoadContext` class. – György Kőszeg May 31 '23 at 13:55
  • Poor example, remoting is not supported in .NET5+ – Hans Passant May 31 '23 at 13:55
  • @HansPassant so why does the documentation list examples of it for .NET 7? – user32882 May 31 '23 at 14:04
  • @GyörgyKőszeg For now I just want to get the example to work. Running as `net472` also doesn't work. Please see edit to OP – user32882 May 31 '23 at 14:11
  • @user32882: Creating a domain with only a name has very limited capabilities. You need to use at least the `Evidence` of the host domain to be able to load types from it. See the updated section of [this](https://stackoverflow.com/a/68257543/5114784) answer that has some links to working real-life projects. And [here](https://github.com/koszeggy/KGySoft.Drawing.Tools/blob/f032e607b0ad2644466105dcc1d4058740e79de3/KGySoft.Drawing.ImagingTools/Model/InstallationInfo.cs#L163) is another example to load/unload assemblies both in .NET Framework by `AppDomain` and .NET Core by `AssemblyLoadContext`. – György Kőszeg May 31 '23 at 14:27
  • @GyörgyKőszeg Those are useful resources, but I'm trying to get this *specific* example to work. If it cannot or shouldn't work I'd like to understand why, I don't care that creating a domain with only a name has limited capabilities for the moment, since even those limited capabilities are failing on my current setup. – user32882 May 31 '23 at 14:34
  • @user32882: In .NET Framework 4.0 and then 4.5 there were many breaking changes regarding Case Access Security. I think this is just an old example that simply does not work anymore as it is, not even with the latest .NET Framework versions. There used to be a link at the bottom of the help pages where you were be able to report issues but it seems it's not there anymore. But you still can file an issue at their GitHub [repo](https://github.com/dotnet/dotnet-api-docs) if you have a finding about the documentation. – György Kőszeg May 31 '23 at 14:52

1 Answers1

1

Quote from https://learn.microsoft.com/en-us/dotnet/core/porting/net-framework-tech-unavailable:

Several technologies available to .NET Framework libraries aren't available for use with .NET 6+, such as app domains, remoting, and code access security (CAS). If your libraries rely on one or more of the technologies listed on this page, consider the alternative approaches mentioned.

For more information on API compatibility, see Breaking changes in .NET.

Application domains Application domains (AppDomains) isolate apps from one another. AppDomains require runtime support and are resource-expensive. Creating more app domains isn't supported, and there are no plans to add this capability in the future. For code isolation, use separate processes or containers as an alternative. To dynamically load assemblies, use the AssemblyLoadContext class.

To make code migration from .NET Framework easier, .NET 6+ exposes some of the AppDomain API surface. Some of the APIs function normally (for example, AppDomain.UnhandledException), some members do nothing (for example, SetCachePath), and some of them throw PlatformNotSupportedException (for example, CreateDomain). Check the types you use against the System.AppDomain reference source in the dotnet/runtime GitHub repository. Make sure to select the branch that matches your implemented version.

More specifically: AppDomains require runtime support and are resource-expensive. Creating more app domains isn't supported, and there are no plans to add this capability in the future.

Hekke
  • 39
  • 3