0

POS for .Net で次のヘルパー クラスを使用して、別の AppDomain 内のハードウェアへの参照を取得します (必要ないくつかの制限を回避します)。<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=neutral, PublicKeyToken=null' またはその依存関係の 1 つを読み込めませんでした。システムは、指定されたファイルを見つけることができません。

これは、AppDomains 間の通信の試行に関連している必要があります。何をすべきかよくわかりません。.Net の Pos に使用される別の AppDomain に "MyAssemblyName" を登録する必要がありますか?

私はプリズムを使用しているので、一部のモジュールは実行時に (出力ディレクトリのサブフォルダーに) ロードされます... 上記の最後のコード スニペットを使用するモジュールを含みます (Scanner = PosHelper.GetHardware....)

4

1 に答える 1

0

私は自分の問題を解決したと信じています。プリズム モジュールは実行時にサブディレクトリ内に読み込まれるため、これを AppDomain に追加して、AppDomain がサブディレクトリ フォルダー内のアセンブリを見つけられるようにする必要がありました。

PrivateBinPath = @"Modules"

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

編集

これは私の問題を部分的にしか解決しませんでした。プログラムの実行中に MarshalByRefObject が破棄されないように、InitializeLifetimeService() をオーバーライドして null を返す必要もありました (デフォルトのタイムアウトは 5 分だと思います)。

また、これは機能するようになりました:

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

しかし、私がこのようなことをしようとすると

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

DoSomething が Serializable および MarshalByRefObject クラスにない場合、AppDomain 間の通信で使用されるすべてのクラスがそれらを持つ必要があるため、うまくいきません。したがって、私が今取り組んでいるのは、WCF の名前付きパイプを使用してデータを渡すことです... および他の同様のソリューションです。

于 2012-09-05T02:32:08.713 に答える