Передача пользовательского объекта через домены приложений - PullRequest
1 голос
/ 07 декабря 2011

Я компилирую плагин, а затем создаю его экземпляр в новом домене приложений. Затем я хочу выполнить метод в объекте плагина, но это приводит к 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);
        }
    }
}

1 Ответ

0 голосов
/ 07 декабря 2011

Это должен быть тип, известный на обеих сторонах вашего общения!

...