如何在託管 C++/CLI 項目中修復 CA2123(覆蓋連結需求應與基本相同)
我無法理解如何為 C++/CLI 項目修復 CA2123。這是一個展示該問題的範例項目:
- 創建一個 C# (.NET 4) 類庫
託管類.cs
命名空間 CSharpLibrary {
public interface IManagedClass { void WriteSomething(); } public class ManagedClass : IManagedClass { public void WriteSomething() { } }}
2)創建一個 C++/CLI 控制台應用程序(VS 2010):
裝配資訊.cpp
#include "stdafx.h" using namespace System; using namespace System::Reflection; using namespace System::Runtime::CompilerServices; using namespace System::Runtime::InteropServices; using namespace System::Security; [assembly:AssemblyTitleAttribute("CPlusPlusCLIConsoleApp")]; [assembly:AssemblyDescriptionAttribute("")]; [assembly:AssemblyVersionAttribute("1.0.*")]; [assembly:ComVisible(false)]; [assembly:CLSCompliantAttribute(false)]; [assembly:SecurityCritical];CPlusPlusCLIConsoleApp.h
#pragma once using namespace CSharpLibrary; using namespace System::Security; typedef void* (__cdecl FACTORY_PROC)(); namespace CPlusPlusCLIConsoleApp { public ref class MainClass : public IManagedClass { public: [SecurityCritical] virtual void WriteSomething(); }; };CPlusPlusCLIConsoleApp.cpp
#include "stdafx.h" #include "CPlusPlusCLIConsoleApp.h" using namespace System; int main(){}; namespace CPlusPlusCLIConsoleApp { [SecurityCritical] void MainClass::WriteSomething() { } };啟用所有 Microsoft 安全規則後,我收到以下警告:
CA2123 覆蓋連結需求應與基本相同
將以下安全屬性添加到“MainClass::WriteSomething(void)”以匹配基礎方法“IManagedClass::WriteSomething(void)”上的 LinkDemand:“SecurityCriticalAttribute”。
CPlusPlusCLIConsoleApp cpluspluscliconsoleapp.cpp 13
我試圖遵循這個StackOverflow 答案的建議,但它沒有修復錯誤。
我知道託管 dll 預設為 SecurityCritical(我不想在我的原始項目中更改它),因為我沒有指定任何 SecurityAttribute。為什麼 C++ CLI dll 不遵循相同的預設值?
我應該遵循哪些步驟來修復此錯誤?(基本上我怎樣才能在 C++ CLI 中創建 WriteSomething 方法 SecurityCritical)
**編輯 1:**我在MSDN上問過同樣的問題。
**編輯 2:**聯繫了微軟,這是一種設計行為。C++\CLI 團隊只是沒有時間為 C++\CLI 實施 Level2 Security。因此 C++\CLI 總是停留在 Level1 Security。可以安全地抑制相同的程式碼分析警告。
這裡的根本問題是您的 C# 和 C++ 程序集使用兩種不同的透明度模型(請參閱http://blogs.msdn.com/b/shawnfa/archive/2009/11/11/transparency-models-a-tale-of -two-levels.aspx和http://blogs.msdn.com/b/shawnfa/archive/2009/11/12/differences-between-the-security-rule-sets.aspx了解兩個級別的詳細資訊)。這是因為 C# 程序集預設編譯為 2 級,但 C++ 程序集由於某些明顯未記錄的原因被編譯器自動強制降至 1 級。不幸的是,後一種行為似乎不可替代。更糟糕的是,它在 VS2012 中似乎並沒有改變,而且看起來產品團隊也沒有考慮很快改變它。
鑑於您不能將 C++ 程序集移動到級別 2,如果您想將執行檔保留在 C++ 中並且它必須包含介面實現,那麼您有幾個可能可行的選擇:
- 通過使用 SecurityRulesAttribute 將 C# 程序集移至級別 1。這大概只有在 C++ 控制台應用程序是 C# 庫的唯一使用者時才可以接受。
- 通過使用 PermissionSetAttribute 將 2 級安全關鍵性“升級”再現為完全信任連結/繼承需求。例如:
[SecurityCritical] [PermissionSet(SecurityAction::LinkDemand, Unrestricted = true)] [PermissionSet(SecurityAction::InheritanceDemand, Unrestricted = true)] virtual void WriteSomething();送出另一個關於Connect的錯誤報告(投票給已關閉的錯誤似乎不是很有用)或在UserVoice上送出功能請求以請求更改編譯器行為也可能是值得的。(鑑於 2 級應該是 .NET 4.0 及更高版本的預設設置,鎖定到 1 級是非常奇怪的。)