Невозможно развернуть экземпляр COM из пользовательского домена - PullRequest
0 голосов
/ 11 октября 2018

Я пытаюсь сделать вызов внутри COM-компонентов из собственного домена.Проблема заключается в том, что, когда я пытаюсь развернуть мой ObjectHandle, исключение Serialization - throw.

Но если я использую текущий AppDomain для создания экземпляра, он работает ....

Сообщение об исключении:

An unhandled exception of type 'System.Runtime.Serialization.SerializationException' occurred in ConsoleApp1.exe
Additional information: Type 'MyAddin.Main' in assembly 'MyAddin, Version=2019.0.1.5, Culture=neutral, PublicKeyToken=null' is not marked as serializable.

И мой код:

using System;

namespace ConsoleApp1
{
    class Program
    {

        static void Main(string[] args)
        {
            string addinPath = "C:\\sources\\MyAddin\\bin\\x64\\Debug\\MyAddin.dll";
            string addinFolder = "C:\\sources\\MyAddin\\bin\\x64\\Debug\\";
            string addinConfigPath = "C:\\sources\\MyAddin\\bin\\x64\\Debug\\MyAddin.dll.config";

            System.AppDomainSetup setup = new System.AppDomainSetup();
            setup.ApplicationBase = addinFolder;
            setup.ConfigurationFile = addinConfigPath;
            setup.ApplicationName = "MyAddin.dll";

            string strClsid = "{2616ad89-f4d1-4dc7-9d9d-a5de101b9085}"; // CLSID of my COM addin

            System.AppDomain customDomain = System.AppDomain.CreateDomain(strClsid,  null,  setup);
            // The type of domain is System.Runtime.Remoting.Proxies.__TransparentProxy}

            // The type of custom domain is 
            System.Type addinComType = System.Type.GetTypeFromCLSID(System.Guid.Parse(strClsid));

            System.Runtime.Remoting.ObjectHandle addinInstanceObjectHandle = customDomain.CreateComInstanceFrom(addinPath, addinComType.FullName); 
            System.Object addinInstance = addinInstanceObjectHandle.Unwrap(); //Throw the Serialization exception when create COM instance from customDomain
            // But working if I did System.AppDomain.CurrentDomain.CreateComInstanceFrom

            System.Reflection.MethodBase myMethod = addinInstance.GetType().GetMethod("connectToEwAPI");
            System.Object[] parameters = { null };
            myMethod.Invoke(addinInstance, parameters);

        }
    }
}

Значит, я делаю что-то глупое?Знаете, чего мне не хватает?

Заранее спасибо за вашу помощь


Редактировать

Я пробовал с более базовой сборкой.Итак, у меня есть сборка C # только с этим кодом

namespace ClassLibrary2
{
    public class Class1
    {
        public Class1()
        {

        }
        public string MyMethod() => "OK";
    }
}

И мой исполняемый код просто

static void Main(string[] args)
{
    string basePath = @"C:\source\MyAddin\ConsoleApp1\ClassLibrary2\bin\Debug";
    string dllName = @"ClassLibrary2";
    string typeName = "ClassLibrary2.Class1";
    string dllFullpath = $"{basePath}\\{dllName}.dll";

    try
    {
        ObjectHandle objectHandle = AppDomain.CurrentDomain.CreateInstanceFrom(dllFullpath, typeName);
        Object addinObject = objectHandle.Unwrap();
        var myAddinMethod = addinObject.GetType().GetMethod("MyMethod");
        string result = myAddinMethod.Invoke(addinObject, null) as string; // Working


        AppDomainSetup setup = new AppDomainSetup()
        {
            ApplicationBase = basePath,
            ApplicationName = dllName,
            ConfigurationFile = dllName + ".dll.config",
            PrivateBinPath = basePath
        };

        AppDomain customDomain = AppDomain.CreateDomain("MyDomain", null, setup);
        ObjectHandle objectHandleFromCustomDomain = customDomain.CreateInstanceFrom(dllFullpath, typeName);
        Object addinObjectFromCustomDomain = objectHandleFromCustomDomain.Unwrap();  // Exception thrown
        var myAddinMethodFromCustomDomain = addinObjectFromCustomDomain.GetType().GetMethod("MyMethod");
        string resultFromCustomDomain = myAddinMethodFromCustomDomain.Invoke(myAddinMethodFromCustomDomain, null) as string;
    }
    catch(Exception e)
    {
        var t = e.Message; // Exception thrown: 'System.Runtime.Serialization.SerializationException' by objectHandleFromCustomDomain.Unwrap()
    }
}

Так что, как вы можете видеть, он работает с доменом по умолчанию, но не собычай ....

Есть идеи?

1 Ответ

0 голосов
/ 13 октября 2018

Если вы хотите получить доступ к объекту через границу AppDomain, вам нужно сделать одну из двух вещей:

  • Сделать класс Serializable, например, добавив [Serializable] атрибут.В этом случае копия объекта сортируется и передается через границу AppDomain.Любые вызываемые вами мембраны будут на копии и не будут влиять на исходный объект.

  • Сделайте класс наследником MarshalByRefObject .В этом случае ссылка на объект маршалируется через границу AppDomain, и любые вызываемые вами члены будут влиять на объект в его исходном AppDomain.

...