2012-03-19 31 views
3

我有一個Visual Studio 2008 C#.NET 3.5類,提供訪問本地庫。該庫有一個Register方法,允許用戶指定將在某個事件中激活的回調。我提供以下的C#實現:包裝本機庫,實現在C#回調#

internal class MyLibHandle : SafeHandleZeroOrMinusOneIsInvalid { /*...*/ } 

internal static class NativeMethods 
{ 
    public delegate void OnSomeEventDelegate (FOO foo, IntPtr user); 

    [DllImport("MyLib.dll", SetLastError = true)] 
    [return: MarshalAs(UnmanagedType.U1)] 
    public static extern bool MyLib_Register(MyLibHandle handle, OnSomeEventDelegate callback, IntPtr user); 
} 

public class MyWrappedLib : IDisposable 
{ 
    private MyLibHandle handle_; 

    private event EventHandler<OnSomeEventArgs> some_event_int_; 

    public event EventHandler<OnSomeEventArgs> SomeEvent 
    { 
     add 
     { 
      if (some_event_int_ == null) 
      { 
       if (!NativeMethods.MyLib_Register(handle_, ReceivedSomeEvent, IntPtr.Zero)) 
       throw new Win32Exception(Marshal.GetLastWin32Error()); 
      } 
      some_event_int_ += value; 
     } 
     remove 
     { 
      some_event_int_ -= value; 
      if (some_event_int_ == null) 
      { 
       if (!NativeMethods.MyLib_DeRegister(handle_, -1)) 
        throw new Win32Exception(Marshal.GetLastWin32Error()); 
      } 
     } 
    } 

    private void ReceivedSomeEvent(FOO foo, IntPtr user) 
    { 
     OnSomeEvent(new OnSomeEventArgs() { foo = foo }); 
    } 

    protected virtual void OnBeacon(OnSomeEventArgs args) 
    { 
     EventHandler<OnSomeEventArgs> evt = some_event_int_; 
     if (evt != null) 
      evt(this, args); 
    } 
} 

這工作,但我得到了幾個不祥敲起警鐘

warning : CA1065 : Microsoft.Design : 'MyWrappedLib.SomeEvent.add(EventHandler<OnSomeEventArgs>)' creates an exception of type 'Win32Exception', an exception type that should not be raised in this type of method. 

warning : CA2122 : Microsoft.Security : 'MyWrappedLib.SomeEvent.add(EventHandler<OnSomeEventArgs>)' calls into 'Marshal.GetLastWin32Error()' which has a LinkDemand. By making this call, 'Marshal.GetLastWin32Error()' is indirectly exposed to user code. 

什麼是處理這種情況的建議呢?我應該創建一個方法來處理事件訂閱而不是傳統的添加;去掉;存取?

由於

回答

1

對於事件訪問,以下的異常類型被允許:

  • System.InvalidOperationException和所有衍生物(包括 System.ObjectDisposedException

  • 系統.NotSupportedException a ND所有衍生

  • ArgumentException的和衍生

爲什麼本地方法返回false? 它會與某些外部條件 連接,還是傳遞了無效參數的結果?

因此,我會將Win32Exception作爲InvalidOperationException, 或ArgumentException的內層進行封裝,具體取決於您的情況。

第二個警告(CA2122)是關於安全的 - 它警告Marshal.GetLastWin32Error執行安全檢查, ,而您的代碼不會。第一次通話時,此安全檢查僅執行一次, 。出於性能原因,之後的所有通話都未驗證訪問權限, 。因此從理論上講,首先可以通過 受信任的用戶進行第一次呼叫,並且所有進一步的呼叫將不受限制。

您需要任何裝飾與下列屬性的事件處理程序:

[的SecurityPermission(SecurityAction.InheritanceDemand,旗幟= SecurityPermissionFlag.UnmanagedCode)]

(它會檢查代碼有權利調用託管代碼) 或禁止此警告,如果您的應用程序中不擔心安全問題。

this question中有很詳細的解釋。