Skip to content

A .NET library for marshalling any object by reference that do not require the object to inherit from MarshalByRefObject.

License

Notifications You must be signed in to change notification settings

Chaoses-Ib/MarshalByRefProxy

Repository files navigation

MarshalByRefProxy

NuGet

A .NET library for marshalling any object by reference that do not require the object to inherit from MarshalByRefObject.

This project is based on ImpromptuInterface.

Basic usage

using MarshalByRefAsProxy;

public interface IProxyInterface
{
    string GetCurrentAppDomainName();
}

// UnmarshallableClass is not required to inherit from IProxyInterface.
// Here we inherit from IProxyInterface just to be able to call CreateInstance() for comparison.
class UnmarshallableClass : IProxyInterface
{
    public string GetCurrentAppDomainName() => AppDomain.CurrentDomain.FriendlyName;
}

class ClassFactory : MarshalByRefObject
{
    public IProxyInterface CreateInstance() => new UnmarshallableClass();

    public IProxyInterface CreateMarshalByRefInstance() => new UnmarshallableClass().MarshalByRefAs<IProxyInterface>();
}

[Test]
public void TestCrossAppDomain()
{
    // Create an application domain named TestDomain
    AppDomain domain = AppDomain.CreateDomain("TestDomain");
    ClassFactory factory = (ClassFactory)domain.CreateInstanceFromAndUnwrap(typeof(ClassFactory).Assembly.Location, typeof(ClassFactory).FullName);

    // Try to marshal an unmarshallable object, which throws a SerializationException
    Assert.Throws<SerializationException>(() => factory.CreateInstance().GetCurrentAppDomainName());

    // Try to marshal an unmarshallable object via MarshalByRefProxy, which works fine
    Assert.AreEqual("TestDomain", factory.CreateMarshalByRefInstance().GetCurrentAppDomainName());
}

Task

class TaskTest : MarshalByRefObject
{
    // Cannot be an async method
    // The return type cannot be IAwaitable<T>
    public IAwaitable GetCurrentAppDomainNameAsync()
    {
        Task.Delay(1000).Wait();
        // IAwaitable is defined by MarshalByRefProxy
        return Task.Run(() => AppDomain.CurrentDomain.FriendlyName).MarshalByRefAs<IAwaitable>();
    }
}        

[Test]
public async Task TestTask()
{
    AppDomain domain = AppDomain.CreateDomain("TestDomain");
    TaskTest test = (TaskTest)domain.CreateInstanceFromAndUnwrap(typeof(TaskTest).Assembly.Location, typeof(TaskTest).FullName);

    string name = (string)await test.GetCurrentAppDomainNameAsync();
    Assert.AreEqual("TestDomain", name);
}

Why can we await IAwaitable? Because C# can await any awaitable expressions, which is exactly what IAwaitable stands for.

Permissions (.NET Framework only)

Assert unrestricted permissions:

using System.Security;
using System.Security.Permissions;

new UnmarshallableClass().MarshalByRefAs<IProxyInterface>(new PermissionSet(PermissionState.Unrestricted));

Todos

  • IAwaitable<T>
  • MarshalByRefWrapper Code Generators
  • MarshalByRefObject Code Generators

About

A .NET library for marshalling any object by reference that do not require the object to inherit from MarshalByRefObject.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published