2012-09-05 48 views
0

我用下面的輔助類與POS對於.NET獲得在一個單獨的AppDomain中的硬件參考(越來越需要<NetFx40_LegacySecurityPolicy enabled="true"/>跨AppDomain的事件發出

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中我嘗試使用事件,像這樣:當它擊中行試圖將拉姆達添加到DataScanned事件中,我得到這個錯誤

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

Could not load file or assembly 'MyAssemlyName, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.

這有可能與嘗試在AppDomain之間進行通信有關。不知道該怎麼做。我是否需要在用於Pos for .NET的單獨AppDomain中註冊「MyAssemblyName」?我使用棱鏡,所以一些模塊在運行時(在我的輸出目錄中的子文件夾中)加載......包括我使用上面的最後一個代碼片段(Scanner = PosHelper.GetHardware ....)的那個模塊。

+0

順便說一句,我不認爲你應該在MarshalByRefObject上添加serializable屬性。可序列化的對象應該是從一個AppDomain傳遞到另一個AppDomain的對象。基於MarshalByRefObject的對象保留在它們的AppDomain上,整個通信通過由.NET Remoting機制透明地創建的代理對象發生。 –

回答

0

我相信我解決了我的問題。由於我的棱鏡模塊在一個子目錄中運行時加載,我需要把它添加到AppDomain中,這樣的AppDomain中可以找到子目錄下的文件夾:

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的是不是一個序列化和MarshalByRefObject的類,它自認爲是所有類擲骰子出來用於AppDomain之間的通信需要有那些。因此,我現在正在考慮使用WCF命名管道來傳遞數據......以及其他類似的解決方案。