InternalsVisibleTo
アセンブリ属性を使用して、.NET クラス ライブラリの内部クラスを単体テスト プロジェクトに表示しようとしています。何らかの理由で、次のようなエラー メッセージが表示され続けます。
'MyClassName' は、保護レベルが原因でアクセスできません
両方のアセンブリが署名されており、属性宣言に正しいキーがリストされています。何か案は?
InternalsVisibleTo
アセンブリ属性を使用して、.NET クラス ライブラリの内部クラスを単体テスト プロジェクトに表示しようとしています。何らかの理由で、次のようなエラー メッセージが表示され続けます。
'MyClassName' は、保護レベルが原因でアクセスできません
両方のアセンブリが署名されており、属性宣言に正しいキーがリストされています。何か案は?
属性で指定された正しい公開鍵を持っていることを絶対に確信していますか? 公開鍵トークンだけでなく、完全な公開鍵を指定する必要があることに注意してください。次のようになります。
[assembly: InternalsVisibleTo("MyFriendAssembly,
PublicKey=0024000004800000940000000602000000240000525341310004000001000100F73
F4DDC11F0CA6209BC63EFCBBAC3DACB04B612E04FA07F01D919FB5A1579D20283DC12901C8B66
A08FB8A9CB6A5E81989007B3AA43CD7442BED6D21F4D33FB590A46420FB75265C889D536A9519
674440C3C2FB06C5924360243CACD4B641BE574C31A434CE845323395842FAAF106B234C2C140
6E2F553073FF557D2DB6C5")]
320 桁程度の 16 進数です。完全な公開キーを指定する必要がある理由がわかりません。おそらく、他のアセンブリ参照で使用されている公開キー トークンだけを使用すると、誰かがフレンド アセンブリの ID を簡単に偽装できる可能性があります。
アセンブリが署名されていないにもかかわらず、同じエラーが発生する場合は、AssemblyInfo.cs ファイルで次の行のいずれかを確認してください。
[assembly: AssemblyKeyFile("")]
[assembly: AssemblyKeyName("")]
これらの行のいずれか (または両方) が存在する場合、[プロパティ] タブにはアセンブリが未署名として表示されますが、InternalsVisibleTo 属性はこれらの行を含むアセンブリを強力に署名されたものとして扱います。これらの行を削除 (またはコメントアウト) するだけで、問題なく動作するはずです。
「フレンド」(テスト)アセンブリがC#/VB.NETではなくC++ / CLIで記述されている場合は、次を使用する必要があることに注意してください。
#using "AssemblyUnderTest.dll" as_friend
プロジェクト参照や通常の#using
ステートメントの代わりに。何らかの理由で、プロジェクト参照UIでこれを行う方法はありません。
InternalsVisibleTo 構文を生成するAssemblyHelper ツールを使用できます。ここに最新バージョンへのリンクがあります。厳密な名前のアセンブリに対してのみ機能することに注意してください。
この属性をすばやく生成するために使用するマクロを次に示します。少しハックですが、動作します。私のマシンで。最新の署名付きバイナリが/bin/debug
. 等々 曖昧等々 とにかく、どうやって鍵を手に入れるかが見えてくるので、ヒントになりますね。時間が許す限り修正/改善してください。
Sub GetInternalsVisibleToForCurrentProject()
Dim temp = "[assembly: global::System.Runtime.CompilerServices." + _
"InternalsVisibleTo(""{0}, publickey={1}"")]"
Dim projs As System.Array
Dim proj As Project
projs = DTE.ActiveSolutionProjects()
If projs.Length < 1 Then
Return
End If
proj = CType(projs.GetValue(0), EnvDTE.Project)
Dim path, dir, filename As String
path = proj.FullName
dir = System.IO.Path.GetDirectoryName(path)
filename = System.IO.Path.GetFileNameWithoutExtension(path)
filename = System.IO.Path.ChangeExtension(filename, "dll")
dir += "\bin\debug\"
filename = System.IO.Path.Combine(dir, filename)
If Not System.IO.File.Exists(filename) Then
MsgBox("Cannot load file " + filename)
Return
End If
Dim assy As System.Reflection.Assembly
assy = System.Reflection.Assembly.Load(filename)
Dim pk As Byte() = assy.GetName().GetPublicKey()
Dim hex As String = BitConverter.ToString(pk).Replace("-", "")
System.Windows.Forms.Clipboard.SetText(String.Format(temp, assy.GetName().Name, hex))
MsgBox("InternalsVisibleTo attribute copied to the clipboard.")
End Sub
上記のすべてに加えて、すべてが正しいように見えても、フレンド アセンブリが頑固に内部の表示を拒否する場合は、ソリューションを再読み込みするか、Visual Studio を再起動することで問題を解決できます。
フレンド アセンブリ (InternalsVisibleTo 属性を含まないアセンブリ) をコンパイルするときは、/out: コンパイラ スイッチを使用する必要があります。
コンパイラは、結果のアセンブリがフレンド アセンブリと見なされるかどうかを判断するために、コンパイルされるアセンブリの名前を知る必要があります。
PublicKey を使用した以前の回答は機能しました: (Visual Studio 2015: 1 行にする必要があります。そうしないと、アセンブリ参照が無効であるか参照できないと不平を言います。PublicKeyToken は機能しませんでした)
[assembly: InternalsVisibleTo("NameSpace.MyFriendAssembly, PublicKey=0024000004800000940000000602000000240000525341310004000001000100F73F4DDC11F0CA6209BC63EFCBBAC3DACB04B612E04FA07F01D919FB5A1579D20283DC12901C8B66A08FB8A9CB6A5E81989007B3AA43CD7442BED6D21F4D33FB590A46420FB75265C889D536A9519674440C3C2FB06C5924360243CACD4B641BE574C31A434CE845323395842FAAF106B234C2C1406E2F553073FF557D2DB6C5")]
@ジョーに感謝
フレンド アセンブリの公開キーを取得するには、次のようにします。
sn -Tp path\to\assembly\MyFriendAssembly.dll
開発者コマンド プロンプト内 ([スタートアップ] > [プログラム] > [Visual Studio 2015] > [Visual Studio ツール] > [VS2015 の開発者コマンド プロンプト])。@Ian Gに感謝します。
ただし、上記の後に私にとってうまくいった最後の仕上げは、共有するライブラリのプロジェクトが署名されるのと同じ方法で、友人のライブラリ プロジェクトに署名することでした。これは新しいテスト ライブラリであるため、まだ署名されていません。
コードの記述方法によっては、追跡が難しい別の可能性があります。
例えば:
// In X
internal static class XType
{
internal static ZType GetZ() { ... }
}
// In Y:
object someUntypedValue = XType.GetZ();
// In Z:
internal class ZType { ... }
上記のように、Y で直接 ZType を参照していない場合、Y を X のフレンドとして追加した後、なぜコードがまだコンパイルされないのか不思議に思うかもしれません。
この場合、コンパイルエラーは間違いなくより役立つ可能性があります。
参照されているアセンブリが複数ある場合は、必要なすべてのアセンブリに InternalsVisibleTo 属性があることを確認してください。場合によっては、この属性を別のアセンブリに追加する必要があることは明らかではなく、メッセージもありません。
InternalsVisibleTo
属性に関する同様の問題を解決しました。すべてが正しいように見えましたが、私が目指していた内部クラスがまだアクセスできない理由を理解できませんでした。
キーのケースを大文字から小文字に変更すると、問題が修正されました。
補足として、sn を使用せずに公開鍵を簡単に取得し、そのオプションを把握したい場合は、便利なプログラムをここからダウンロードできます。公開キーを決定するだけでなく、"assembly: InternalsVisibleTo..." 行を作成して、クリップボードにコピーしてコードに貼り付けることができます。