Кросс-доменные проблемы

Я использую следующий вспомогательный класс с POS для.Net, чтобы получить ссылку на оборудование в отдельном домене приложений (обойдя некоторые ограничения, требующие <NetFx40_LegacySecurityPolicy enabled="true"/>

public static class PosHelper
{
    private static AppDomain _posAppDomain { get; set; }

    private static AppDomain PosAppDomain
    {
        get
        {
            if (_posAppDomain == null)
            {
                AppDomainSetup currentAppDomainSetup = AppDomain.CurrentDomain.SetupInformation;
                AppDomainSetup newAppDomainSetup = new AppDomainSetup()
                {
                    ApplicationBase = currentAppDomainSetup.ApplicationBase,
                    LoaderOptimization = currentAppDomainSetup.LoaderOptimization,
                    ConfigurationFile = currentAppDomainSetup.ConfigurationFile
                };
                newAppDomainSetup.SetCompatibilitySwitches(new[] { "NetFx40_LegacySecurityPolicy" });

                _posAppDomain = AppDomain.CreateDomain("POS Hardware AppDomain", null, newAppDomainSetup);
            }
            return _posAppDomain;
        }
    }

    public static T GetHardware<T>() where T : PosHardware, new()
    {
        T hardware = (T)PosAppDomain.CreateInstanceFromAndUnwrap(Assembly.GetAssembly(typeof(T)).Location, typeof(T).FullName);

        hardware.FindAndOpenDevice();
        return hardware;
    }
}

У меня есть базовый класс для обработки, когда сканер POS сканирует данные. В этом классе у меня есть событие, которое я хочу запустить при сканировании данных. Вот фрагмент:

public class ScannerDevice : PosHardware
{
    public event Action<string> DataScanned;
    ...
        _scanner.DataEvent += new DataEventHandler(Scanner_DataEvent);
    ...
    private void Scanner_DataEvent(object sender, DataEventArgs e)
    {
        ASCIIEncoding encoder = new ASCIIEncoding();

        if (DataScanned != null)
            DataScanned(encoder.GetString(_scanner.ScanDataLabel));

        _scanner.DataEventEnabled = true; // enable for subsequent scans
    }

Обратите внимание, что абстрактный класс PosHardware наследует MarshalByRefObject и отмечен [Serializable]В моем основном AppDomain я пытаюсь использовать событие так:

    Scanner = PosHelper.GetHardware<ScannerDevice>();
    Scanner.DataScanned += m =>
    {
        Debug.WriteLine(m);
    };

Когда он попадает в строку, пытаясь добавить лямбду к событию DataScanned, я получаю эту ошибку:

Не удалось загрузить файл или сборку 'MyAssemlyName, Version=1.0.0.0, Culture= нейтральный, PublicKeyToken=null' или одну из ее зависимостей. Система не может найти указанный файл.

Это должно быть связано с попыткой установить связь между доменами приложений. Не совсем уверен, что делать. Нужно ли регистрировать "MyAssemblyName" в отдельном домене приложений, используемом для Pos для.Net?

Я использую призму, поэтому некоторые модули загружаются во время выполнения (в подпапке моего выходного каталога)... включая тот, в котором я использую последний фрагмент кода выше (Scanner = PosHelper.GetHardware....)

1 ответ

Я считаю, что я решил свою проблему. Поскольку мои призменные модули загружаются во время выполнения в подкаталоге, мне нужно было добавить это в домен приложений, чтобы домен приложений мог находить сборки в папке подкаталогов.

PrivateBinPath = @"Modules"

http://msdn.microsoft.com/en-us/library/system.appdomainsetup.privatebinpath.aspx

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

Это только частично решило мою проблему. Мне также пришлось переопределить InitializeLifetimeService() и вернуть null, чтобы мои MarshalByRefObject не удалялись во время работы программы (я полагаю, что время ожидания по умолчанию составляет 5 минут).

Кроме того, теперь это работает:

Scanner.DataScanned += m =>
    {
        Debug.WriteLine(m);
    }

но когда я пытаюсь что-то вроде этого

Scanner.DataScanned += m =>
    {
        DoSomething(m);
    }

Если DoSomething не входит в класс Serializable и MarshalByRefObject, он выпадает из-под контроля, поскольку все классы, используемые в связи между AppDomain, должны иметь их. Поэтому сейчас я рассматриваю использование именованных каналов WCF для передачи данных... и других подобных решений.

Другие вопросы по тегам