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.
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());
}
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.
Assert unrestricted permissions:
using System.Security;
using System.Security.Permissions;
new UnmarshallableClass().MarshalByRefAs<IProxyInterface>(new PermissionSet(PermissionState.Unrestricted));
-
IAwaitable<T>
- MarshalByRefWrapper Code Generators
- MarshalByRefObject Code Generators