2

I'm migrating an app from .NET Framework to .NET 5.0.

In my previous implementation, I was dynamically reading assemblies from an external source, then loading them into different AppDomains, then running an Action through a CrossAppDomainDelegate.

Code sample which would run for each assembly:

var setup = new AppDomainSetup
{
    ApplicationBase = AppDomain.CurrentDomain.BaseDirectory,
};

var domain = AppDomain.CreateDomain($"MyDomain", null, setup);
var del = new CrossAppDomainDelegate(action); // The action I'm running

domain.DoCallBack(del);

In .NET 5.0, I can still create the domain (even though I can't use the Setup as before) but I can't seem to find a way to run the action through a delegate, since CrossAppDomainDelegate is no longer supported.

Any ideas on how to achieve this? Is it even possible? If not, what's another way to achieve this functionality?

  • check related: https://stackoverflow.com/questions/6242573/simplest-way-to-make-cross-appdomain-call – valerysntx Jul 19 '21 at 18:53
  • @valerysntx: Given that thread is from a decade ago and pertains to the .NET Framework, I doubt that's going to address the OP's question, which is specific to the new .NET 5. – Jeremy Caney Jul 19 '21 at 18:58
  • @JeremyCaney, I think it's related, since ```CreateInstanceAndUnwrap``` could be used – valerysntx Jul 19 '21 at 19:47

1 Answers1

1

Consider using CreateInstanceAndUnwrap method of AppDomain class with MarshalByRefObject proxy implementation of cross-app-delegate, like:


public interface IRuntime
{
    object Run<T>(Expression<Func<T>> del);
}


public class Runtime : MarshalByRefObject, IRuntime
{
    public object Run<T>(Expression<Func<T>> del)
    {
        return del.Compile().Invoke();
    }
}


void Main()
{
    AppDomain childDomain = null;
    try
    {


        // Create the child AppDomain 
        childDomain = AppDomain.CurrentDomain;
        // AppDomain.CreateDomain("Your Child AppDomain"); //supported? NET5.0

        // Create an instance of the runtime in the second AppDomain. 
        // A proxy to the object is returned.
        IRuntime runtime = (IRuntime) childDomain.CreateInstanceAndUnwrap(
                                       typeof(Runtime).Assembly.FullName,                                                                    
                                       typeof(Runtime).FullName);



        // start the runtime.  call will marshal into the child runtime appdomain
        runtime.Run<string>(() => "hello!").Dump();
    }
    finally
    {
        // runtime has exited, finish off by unloading the runtime appdomain
        if (childDomain != null && childDomain != AppDomain.CurrentDomain) AppDomain.Unload(childDomain);
    }

}

valerysntx
  • 506
  • 3
  • 7
  • Thank you @valerysntx, worked like a charm! One thing I changed is the delegate to run an Action instead of Func (which is more fitting for my case), then the Run function became void instead of returning an object, so I couldn't dump the object anymore after the call. – Joseph Nasr Jul 21 '21 at 13:52
  • @JosephNasr, I'm glad I could help You. While simply passing Actions still works, the intent of using ```Expression>``` looks reasonable, little improvement would be parameters passing, ```... Run(Expression>, params object[]? args) ``` Such we could make linq predicates (*Delegates*) working cross-domain too! – valerysntx Jul 21 '21 at 22:51
  • https://dzone.com/articles/who-ever-said-linq-predicates- – valerysntx Jul 21 '21 at 22:59
  • MS [docs](https://learn.microsoft.com/en-us/dotnet/core/porting/net-framework-tech-unavailable) say this is not supported, are you sure this actually works ? – Menahem May 14 '23 at 12:44