跨appdomain传递自定义对象

本文关键字:自定义 对象 appdomain | 更新日期: 2023-09-27 18:17:12

我编译了一个插件,然后在一个新的AppDomain中创建了它的实例。然后我想在插件对象中执行一个方法,但这会导致ArgumentException:

    "Object of type System.MarshalByRefObject can not be converted to type Data"

下面的代码应该是可编译的,并导致上面的异常。要使其工作,您还必须签署程序集(项目->属性->签名->签署程序集->新建…)

IPlugin.cs:

using System;
namespace Plugin
{
    [Serializable]
    class Data : MarshalByRefObject
    {
        int value;
    }
    interface IPlugin
    {
        void DoStuff(Data data);
    }
}

Program.cs:

using System;
using System.CodeDom.Compiler;
using System.IO;
using System.Security.Policy;
using System.Security;
using System.Security.Permissions;
using System.Reflection;
namespace Plugin
{
    class Program
    {
        public class Sandbox : MarshalByRefObject
        {
            const string BaseDirectory = "Untrusted";
            const string DomainName = "Sandbox";
            private object instance;
            public static Sandbox Create()
            {
                var setup = new AppDomainSetup()
                {
                    ApplicationBase = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, BaseDirectory),
                    ApplicationName = DomainName,
                    DisallowBindingRedirects = true,
                    DisallowCodeDownload = true,
                    DisallowPublisherPolicy = true
                };
                Evidence ev = new Evidence();
                ev.AddHostEvidence(new Zone(SecurityZone.Internet));
                var permissions = new PermissionSet(PermissionState.None);
                permissions.AddPermission(new ReflectionPermission(ReflectionPermissionFlag.RestrictedMemberAccess));
                permissions.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution));
                StrongName fullTrustAssembly = typeof(Sandbox).Assembly.Evidence.GetHostEvidence<StrongName>();
                var domain = AppDomain.CreateDomain(DomainName, null, setup, permissions, fullTrustAssembly);
                return (Sandbox)Activator.CreateInstanceFrom(domain, typeof(Sandbox).Assembly.ManifestModule.FullyQualifiedName, typeof(Sandbox).FullName).Unwrap();
            }
            public bool CreateInstance(string assemblyPath, string scriptType)
            {
                new FileIOPermission(FileIOPermissionAccess.Read | FileIOPermissionAccess.PathDiscovery, assemblyPath).Assert();
                var assembly = Assembly.LoadFrom(assemblyPath);
                CodeAccessPermission.RevertAssert();
                Type type = assembly.GetType(scriptType);
                if (type == null)
                    return false;
                instance = Activator.CreateInstance(type);
                return instance != null;
            }
            public object Execute(string method, params object[] parameters)
            {
                Type type = instance.GetType();
                MethodInfo info = type.GetMethod(method);
                return info.Invoke(instance, parameters);
            }
        }
        private static void CompileToFile(string code, string ifaceFile, string output)
        {
            CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");
            CompilerParameters p = new CompilerParameters();
            p.GenerateInMemory = false;
            p.GenerateExecutable = false;
            p.OutputAssembly = output;
            provider.CompileAssemblyFromSource(p, code, ifaceFile);
        }
        private static string code = @"
using Plugin;
class MyPlugin : IPlugin
{
    public void DoStuff(Data data)
    {
    }
}
";
        static void Main(string[] args)
        {
            string iface = System.IO.File.ReadAllText(@"C:'Documents and Settings'markus.BLUE'mina dokument'visual studio 2010'Projects'Plugin'Plugin'IPlugin.cs");
            string pluginObjectFile = System.IO.Path.GetTempFileName();
            CompileToFile(code, iface, pluginObjectFile);
            Sandbox s = Sandbox.Create();
            s.CreateInstance(pluginObjectFile, "MyPlugin");
            Data data = new Data();
            s.Execute("DoStuff", data);
        }
    }
}

跨appdomain传递自定义对象

必须是通信双方都知道的类型!