Assembly.Load

Assembly.Loadも、アセンブリをロードするメソッド。

Assembly.Load Method (System.Reflection) | Microsoft Docs

".dll"を省略できたり、完全限定名を指定してロードできる。

空のプロジェクト
空のプロジェクト

空のプロジェクト。

MainClass.cs
MainClass.cs

MainClass.cs。

"ClassLibrary"だけでロードしてみる。

DLLはEXEと同じ場所
DLLはEXEと同じ場所

DLLはEXEと同じ場所。

asm1 = ClassLibrary, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
続行するには何かキーを押してください . . .

こうなる。
完全限定名での指定もできるが、LoadFileで絶対パスの指定ができるので、絶対パスが違う時点で完全限定名での区別が必要なケースってどういうのだろうとおもった。

Sample/dotnet/Assembly/Load/src/Assembly_ at master · bg1bgst333/Sample · GitHub

Assembly.LoadFile

Assembly.LoadFileでも、アセンブリをロードできる。

Assembly.LoadFile Method (System.Reflection) | Microsoft Docs
.NETアセンブリでのLoadFileとLoadFromの違い - コードログ

LoadFileは絶対パスを指定する。
同じdllでもパスの位置が違うファイルと区別される模様。

空のプロジェクト
空のプロジェクト

空のプロジェクト。

MainClass.cs
MainClass.cs

MainClass.cs。

Lib1フォルダ作成
Lib1フォルダ作成

Lib1フォルダ作成。

DLLを置く
DLLを置く

DLLを置く。

Lib2作成
Lib2作成

Lib2作成。

そこにも置く
そこにも置く

そこにも置く。

実際には、それぞれのDLLを置いた場所の絶対パスを指定する。

asm1 = ClassLibrary, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
asm2 = ClassLibrary, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
asm1.CodeBase != asm2.CodeBase
続行するには何かキーを押してください . . .

CodeBaseが違うということは場所が違うということ。

Sample/dotnet/Assembly/LoadFile/src/Assembly_ at master · bg1bgst333/Sample · GitHub

Assembly.LoadFrom

Assembly.LoadFromで、指定のDLLやEXEのアセンブリをロードする。

Assembly.LoadFrom Method (System.Reflection) | Microsoft Docs
動的にDLLファイルのクラスメソッドを呼び出す (Reflectionを用いたアセンブリの動的呼び出し) (C#プログラミング)

空のプロジェクト
空のプロジェクト

空のプロジェクト。

MainClass.cs
MainClass.cs

MainClass.cs。

DLLのファイル名だけ指定。

EXEと同じ場所に置く
EXEと同じ場所に置く

EXEと同じ場所に置く。

Releaseも同様に
Releaseも同様に

Releaseも同様に。

asm = ClassLibrary, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
続行するには何かキーを押してください . . .

このようにアセンブリ情報が出る。

Sample/dotnet/Assembly/LoadFrom/src/Assembly_ at master · bg1bgst333/Sample · GitHub

Assembly

Assemblyクラスは、クラスライブラリや実行ファイルなどのアセンブリ情報を持つ。

Assembly Class (System.Reflection) | Microsoft Docs

空のプロジェクト
空のプロジェクト

空のプロジェクト。

MainClass.cs
MainClass.cs

MainClass.cs。

DLLを置く
DLLを置く

プロジェクトファイルと同じ場所に、DLLを置く。

参照の追加
参照の追加

参照の追加で、

ClassLibrary.dllを選択
ClassLibrary.dllを選択

ClassLibrary.dllを選択。

typeofでClassLibraryClassのTypeであるtypeを取得したら、type.AssemblyでAssemblyオブジェクトasmを取得。

asm = ClassLibrary, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
続行するには何かキーを押してください . . .

asmの中身はアセンブリ情報。

Sample/dotnet/Assembly/Assembly/src/Assembly_ at master · bg1bgst333/Sample · GitHub

DllImportAttribute

DllImportAttributeは、C++などで書かれた外部ライブラリ(DLL)のメソッドを宣言する時に付ける属性。

DllImportAttribute Class (System.Runtime.InteropServices) | Microsoft Docs

MessageBoxなど、ANSI関数とUnicode関数が別れている場合は、呼び出す関数によっては文字コードを指定しておかないと文字化けの可能性がある。

空のプロジェクト
空のプロジェクト

空のプロジェクトで、

MainClass.cs
MainClass.cs

MainClass.csを追加。

MessageBoxWを呼び出す。

MessageBox function (winuser.h) | Microsoft Docs

Unicode関数なので、CharSetにCharSet.Unicodeを指定。
hWndはIntPtrに、LPCWSTRはstringに、UINTはuintに。

MessageBoxWが表示される
MessageBoxWが表示される

MessageBoxWが表示される。

終了
終了

そして終了。

Sample/dotnet/DllImportAttribute/DllImportAttribute/src/DllImportAttribute_ at master · bg1bgst333/Sample · GitHub

extern

C++などで書かれた外部ライブラリ(DLL)のメソッドを呼び出す場合に、externでそのメソッドを宣言する必要がある。
DllImport属性と共に使う。

extern 修飾子 - C# リファレンス | Microsoft Docs
Win32 APIやDLL関数を呼び出すには?:.NET TIPS - @IT

空のプロジェクト
空のプロジェクト

空のプロジェクトで、

MainClass.cs
MainClass.cs

MainClass.csを追加。

WindowsAPIのBeepを呼び出すコードを書く。
引数や戻り値型がC++C#では違うので、この辺は適切に変えなくてはならない。
(といいつつ、互換性がありそうなのを適当に。)

Beep 440Hz Start!
Beep 440Hz End!
続行するには何かキーを押してください . . .

伝わらないと思うけど、これもStartとEndの間で信号音が3秒鳴る。

Sample/cs/extern/extern/src/extern at master · bg1bgst333/Sample · GitHub

ConditionalAttribute

ConditionalAttributeは、指定のシンボルマクロが定義されている時にそのメソッドを呼び出す属性。

ConditionalAttribute Class (System.Diagnostics) | Microsoft Docs
条件付きの呼び出し (ConditionalAttribute) - Programming/.NET Framework - 総武ソフトウェア推進所

これ自体は属性のトピックでも扱ったが、今回はConditionalAttributeが複数指定もできるという点について扱う。

空のプロジェクト
空のプロジェクト

空のプロジェクト

MainClass.cs
MainClass.cs

MainClass.csを追加。
まずは、

// 名前空間の登録
using System;               // 共通データ型と基本クラス(System名前空間)
using System.Diagnostics;   // システムプロセスやイベントログとの対話するためのクラス.(System.Diagnostics名前空間)

// メインクラス
class MainClass // MainClassクラスの定義
{

    // メインメソッド
    static void Main()  // Mainメソッドの定義
    {

        // 属性付きメソッドTestを呼ぶ.
        Test(); // Testを呼ぶ.

        // "ABCDE"と出力.
        Console.WriteLine("ABCDE"); // Console.WriteLineで"ABCDE"と出力.

    }

    // 属性付きメソッドTest
    [Conditional("TEST"), Conditional("TEST2")]   // "TEST"または"TEST2"が定義されていれば呼ばれる.
    static void Test()
    {

        // "Test"と出力.
        Console.WriteLine("Test");  // Console.WriteLineで"Test"と出力.

    }

}

これだと、

ABCDE
続行するには何かキーを押してください . . .

Test()は呼ばれず、"Test"も出力されない。
次に、

// シンボルの定義
#define TEST

// 名前空間の登録
using System;               // 共通データ型と基本クラス(System名前空間)
using System.Diagnostics;   // システムプロセスやイベントログとの対話するためのクラス.(System.Diagnostics名前空間)

// メインクラス
class MainClass // MainClassクラスの定義
{

    // メインメソッド
    static void Main()  // Mainメソッドの定義
    {

        // 属性付きメソッドTestを呼ぶ.
        Test(); // Testを呼ぶ.

        // "ABCDE"と出力.
        Console.WriteLine("ABCDE"); // Console.WriteLineで"ABCDE"と出力.

    }

    // 属性付きメソッドTest
    [Conditional("TEST"), Conditional("TEST2")]   // "TEST"または"TEST2"が定義されていれば呼ばれる.
    static void Test()
    {

        // "Test"と出力.
        Console.WriteLine("Test");  // Console.WriteLineで"Test"と出力.

    }

}

と#defineで"TEST"を定義すると、

Test
ABCDE
続行するには何かキーを押してください . . .

と"Test"が出力される。
そして、

と#defineで"TEST2"を定義すると、

Test
ABCDE
続行するには何かキーを押してください . . .

と"Test"が出力される。

Sample/dotnet/ConditionalAttribute/ConditionalAttribute/src/ConditionalAttribute_ at master · bg1bgst333/Sample · GitHub