対象: root/programs/CS/Frameworks / ブランチ: develop
最終更新: 2026-10-17
本書は コーディング・エージェントが本リポジトリで作業する際の Context を目的とした分析結果である。 「どこに何があるか」「どの規約に従うべきか」「何を壊しやすいか」を記す。
本書は俯瞰である。 アセンブリごとの詳細は、下の案内表の文書が一次情報を持つ(#613)。 本書には、領域をまたいで効くこと(呼び出しの流れ、例外モデル、条件コンパイル、ビルド順、バージョン管理、横断の落とし穴)を残す。
Open棟梁 (OpenTouryo) は、日立ソリューションズ発の .NET 用アプリケーション・フレームワーク(Apache-2.0)。
2007年から継続開発されており、P層(画面)/B層(業務ロジック)/D層(データアクセス)の3層モデルと、
「UOC」= User Own Coding(利用者が実装する拡張ポイント) という設計思想が全体を貫く。
- 上流ドキュメント:
OpenTouryoDocumentsリポジトリ(本リポジトリ外) - 配布形態: NuGet パッケージ(
Touryo.Infrastructure.*/ アセンブリ名OpenTouryo.*) - プロジェクト・ポリシーは リポジトリ ルートの
AGENTS.md(CLAUDE.mdはそれへのポインタ) に定義済み。 → エージェントは git 操作(add/commit/push/checkout/branch/reset/restore/stash)を行わない。 作業結果はワーキング ツリーに残し、変更内容を報告するに留める。
作業対象のディレクトリに近い文書から読む。 各文書の末尾に「落とし穴」と「作業チェックリスト」がある。
| ディレクトリ | 文書 | 扱うこと |
|---|---|---|
Infrastructure/ |
Infrastructure/ANALYSIS.md |
部品とテンプレートの区別、アセンブリの依存の向き、ソリューションと参照の方式、TFM と出力先、ビルド対象外のファイル、ServiceInterface、VB 版 |
Infrastructure/Public/ |
Public/ANALYSIS.md |
汎用ライブラリ(Db / Dto / Str / IO / Log / Util / Reflection ほか)と Dam* |
Infrastructure/Public/Security/ |
Public/Security/ANALYSIS.md |
暗号・署名・JWT・鍵交換・パスワード ハッシュ |
Infrastructure/Framework/ |
Framework/ANALYSIS.md |
P/B/D の親クラス、通信制御、例外、認証(OAuth2 / OIDC / SAML2)、Framework.RichClient |
Infrastructure/Business/ |
Business/ANALYSIS.md |
業務フレームワーク(サーバ側のテンプレート)。データ プロバイダの選択、MyBaseDao / CmnDao、_3TierEngine |
Infrastructure/Business/RichClient/ |
Business/RichClient/ANALYSIS.md |
同上(WinForms / WPF) |
Infrastructure/CustomControl/ |
CustomControl/ANALYSIS.md |
ASP.NET Web Forms のカスタム コントロール |
Infrastructure/CustomControl/RichClient/ |
CustomControl/RichClient/ANALYSIS.md |
WinForms のカスタム コントロール |
Tools/ |
Tools/ANALYSIS.md |
開発支援ツール(墨壺・DPQuery・ZIP の HTTP 配布) |
Tests/ |
Tests/README.md |
テストの区分(Golden / NUnit / Else)と置き場の決め方 |
| ディレクトリ | アセンブリ | 種類 | 役割 |
|---|---|---|---|
Public/ |
OpenTouryo.Public |
部品 | 汎用ライブラリ。フレームワーク非依存で単体利用可 |
Public/Security/ |
OpenTouryo.Public.Security |
部品 | 暗号・署名・JWT/JWS/JWE・鍵交換・パスワードハッシュ |
Public/Db/Dam*/ |
OpenTouryo.Dam* |
部品 | DBMS 別データアクセス制御(Dam)の別アセンブリ |
Framework/ |
OpenTouryo.Framework |
部品 | フレームワーク中核(P/B/D の親クラス、通信、認証、例外) |
Framework/RichClient/ |
OpenTouryo.Framework.RichClient |
部品 | WinForms/WPF 向け |
Business/ |
OpenTouryo.Business |
テンプレート | 業務フレームワーク。アプリ側でカスタマイズ前提 |
Business/RichClient/ |
OpenTouryo.Business.RichClient |
テンプレート | 同上(リッチクライアント) |
CustomControl/ |
OpenTouryo.CustomControl |
テンプレート | ASP.NET Web Forms カスタム コントロール(net48 のみ) |
CustomControl/RichClient/ |
OpenTouryo.CustomControl.RichClient |
テンプレート | WinForms カスタム コントロール |
ServiceInterface/ |
— | ホスト | サービス公開ホスト(ASP.NET WebAPI / WCF-TCP)。net48 のみ |
部品とテンプレートで、変更の影響の読み方が違う(部品は公開 API の互換、テンプレートは VB 版の追随)。
依存の向き・参照の方式・出力先は Infrastructure/ANALYSIS.md 3〜5 節。
DaoGen_Tool(墨壺。D 層の自動生成)/ DPQuery_Tool(DPQ の編集・検証)/ DeployZipPackWithHTTP(ZIP の HTTP 配布)。
構成・検証・落とし穴は Tools/ANALYSIS.md、CLI での使い方は各ツールの README.md。
判定の方式でフォルダを分けている(#610)。区分ごとの中身と、置き場の決め方は
Tests/README.md が一次情報。運用(何をいつ回すか)は TESTING.md。
テスト プロジェクトはフレームワークを ProjectReference ではなく HintPath で参照する。
→ フレームワークを先にビルドしないとテストは古い DLL を見る。
[P層] 画面コード
BaseController(Web Forms) / BaseMVController(MVC5) / BaseMVControllerCore(ASP.NET Core MVC)
↓ MyBase*Controller(Business層のテンプレート)を継承してアプリが実装
↓
[通信] CallController.Invoke(serviceName, parameterValue)
↓ ProtocolNameService でプロトコル解決(TMProtocolDefinition.xml)
↓ InProcessNameService で assembly/class 解決(TMInProcessDefinition.xml)
↓ Latebind.InvokeMethod → "DoBusinessLogic"
↓
[B層] BaseLogic.DoBusinessLogic(parameterValue, iso)
├ UOC_ConnectionOpen … Dam 生成/Connection Open/BeginTransaction
├ UOC_PreAction … ACCESS ログ等
├ UOC_DoAction … ★業務処理。MyFcBaseLogic は "UOC_" + MethodName へ Latebind 振り分け
├ UOC_AfterAction
├ Commit(_dam と _dams[key] すべて)
├ UOC_AfterTransaction
└ catch → Rollback → UOC_ABEND(例外種別ごとに 3 オーバーロード)
finally → ConnectionClose
↓
[D層] BaseDao ← MyBaseDao ← CmnDao / アプリ個別 Dao
↓
[DAM] BaseDam ← DamSqlSvr / DamODBC / DamOLEDB / DamMySQL / DamPstGrS / DamManagedOdp
各層の中身: 通信は Framework/ANALYSIS.md 3 節、
UOC_ConnectionOpen(データ プロバイダの選択)は Business/ANALYSIS.md 3.1 節、
Dam は Public/ANALYSIS.md 4 節。
BaseParameterValue(ScreenId / ControlId / MethodName / ActionType、すべて読み取り専用)
→ MyParameterValue(+ MyUserInfo User)→ _3TierParameterValue(検索条件・ソート・ページング等)
BaseReturnValue(ErrorFlag / ErrorMessageID / ErrorMessage / ErrorInfo)
→ MyReturnValue → _3TierReturnValue
[Serializable]。WS 越えのため。ActionTypeは"SQL%common"のように%区切りの複合文字列。 先頭要素だけがフレームワーク(Businessのテンプレート)の解釈するデータ プロバイダ選択キーで、UOC_ConnectionOpenで分岐する。使えるキーと、どれにも当たらなければ黙って SQL Server になることはBusiness/ANALYSIS.md3.1 節。2 番目以降はアプリ(サンプル)側の約束である。
MyFcBaseLogic.UOC_DoAction は "UOC_" + parameterValue.MethodName を リフレクションで呼ぶ。
戻り値は ref では戻らない(例外時に失われる)ため、this.ReturnValue プロパティ経由で受け渡す。
private void UOC_SelectCount(TestParameterValue p) // private でよい
{
TestReturnValue r = new TestReturnValue();
this.ReturnValue = r; // ★必ず冒頭で設定する
...
}ReturnValue の setter は WasCalledFromDoBusinessLogic フラグを見ており、
DoBusinessLogic 経由でない呼び出しでは FrameworkException を投げる。
| 例外 | 意味 | DoBusinessLogic の挙動 |
|---|---|---|
BusinessApplicationException |
業務例外(想定内) | Rollback → ErrorFlag=true を戻り値に設定 → リスローしない |
BusinessSystemException |
業務システム例外 | Rollback → UOC_ABEND → リスロー |
Exception(その他) |
想定外 | Rollback → UOC_ABEND(ref) → リスローしない(UOC 側で必要なら throw) |
FrameworkException |
フレームワーク内部エラー | 上位へ |
すべて messageID プロパティを持つ(Information は BusinessApplicationException のみ)。
- SPQ 静的パラメタライズド・クエリ …
.sqlファイル - DPQ 動的パラメタライズド・クエリ …
.xmlファイル。<WHERE>/<IF>/<ELSE>で パラメタが設定されている条件行だけを動的に組み立てる(SQL インジェクション耐性を保ったまま動的 WHERE を実現)
<ROOT>
SELECT [ShipperID],[CompanyName] FROM [Shippers]
<WHERE>
WHERE
<IF>AND [ShipperID] = @ShipperID<ELSE>AND [ShipperID] IS NULL</ELSE></IF>
<IF>AND [CompanyName] LIKE @CompanyName_Like</IF>
</WHERE>
</ROOT>サンプルは root/files/resource/Sql/(sqlserver / oracle / mysql / pstgrs / db2 / hirdb / ole_odbc 別サブディレクトリあり)。
| 層 | クラス | 所管の文書 |
|---|---|---|
| Dam(DBMS 差異の吸収) | BaseDam と Dam* |
Public/ANALYSIS.md 4 節 |
| Dao の親 | BaseDao |
Framework/ANALYSIS.md 6 節 |
| Dao のテンプレート | MyBaseDao(SetSqlByFile2・SQLTRACE)/ CmnDao(汎用 Dao)/ _3TierEngine |
Business/ANALYSIS.md 3.3・4 節 |
CmnDaoはBaseDaoのメソッドをnewで隠蔽してpublic化している(overrideではない。12 節 3)。_3TierEngineはDaoGen_Toolが生成するコードとセットで使う。net48 専用(6.3 節)。
DbEnum.IsolationLevelEnum: NotConnect(接続しない) / NoTransaction / ReadUncommitted /
ReadCommitted / RepeatableRead / Serializable / Snapshot / DefaultTransaction / User。
User は「B層テンプレート側で決める」の意で、MyBaseLogic では ReadCommitted にフォールバックする。
D層に非同期の API は無い。 BaseDam は ExecuteReader / ExecuteScalar /
ExecuteNonQuery の同期版だけを持つ。
上位の ~Async も、別スレッドで同期版を走らせているだけである。
// CallController.cs / BaseLogic.cs
return Task<...>.Factory.StartNew(() => {
return this.Invoke(...); // 同期版
});これはブロックの移動であって、除去ではない。 呼び出し元のスレッドは解放されるが、プールのスレッドが 1 本、DB 応答の間ずっと塞がる。
業務系の DBMS アプリケーションでは、非同期のサポートは重要ではないと判断した。
1 要求が 1 コネクションを保持する設計だからである。
UOC_ConnectionOpen で Dam を作り、コネクションとトランザクションを開く
→ B層の処理がすべて終わるまで保持 → Commit / Rollback
同時実行数は、スレッド数ではなくコネクション プールの上限で決まる。 スレッドを解放できても、プールが空かなければ次には進めない。 非同期化で増えるのは「待てる要求の数」であって、 「同時に処理できる要求の数」ではない。
| 論点 | 既存の機構 |
|---|---|
| 同時実行数の制御 | コネクション プール(上限) |
| 応答しない処理の打ち切り | FxSqlCommandTimeout(既定 30 秒) |
非同期化でしか得られないのは「実行中の中断」だけだが、
業務システムでは利用者が処理を中断する場面が限られ、多くは CommandTimeout で足りる。
足すとしても、一様には効かない。
DbCommand の ~Async は、プロバイダが上書きしなければ
基底クラスの既定実装=呼び出し元スレッドで同期実行になる。
await してもそこで止まるため、今より悪くなり得る。
| Dam | ライブラリ | 非同期の実体 |
|---|---|---|
DamSqlSvr |
Microsoft.Data.SqlClient |
真の非同期 |
DamPstGrS |
Npgsql |
真の非同期 |
DamMySQL |
MySql.Data |
要検証 |
DamManagedOdp |
Oracle.ManagedDataAccess |
要検証 |
DamODBC / DamOLEDB |
標準 | 効果なし(既定実装) |
~Asyncという名前は「非同期である」と読まれる。 効かないプロバイダに足すと、名前だけが非同期になり、実態を隠す。
設定ファイルの仕組み(種類・読み込み順・環境変数での上書き・%変数% の展開・パスの落とし穴)は
CONFIGURATION.md が一次情報。 本節は、フレームワークが読む定義ファイルとキーの俯瞰に留める。
| appSettings キー | ファイル | 用途 |
|---|---|---|
FxXMLMSGDefinition |
MSGDefinition[_ja/_zh-CN].xml |
メッセージ ID → 文言(GetMessage) |
FxXMLSPDefinition |
SPDefinition.xml |
共有プロパティ(GetSharedProperty) |
FxXMLSCDefinition |
SCDefinition.xml |
画面遷移定義(BaseController の遷移チェック) |
FxXMLTCDefinition |
TCDefinition.xml |
トランザクション定義(TransactionControl)。接続文字列キー+分離レベル(nc/nt/uc/rc/rr/sz/ss/df) |
FxXMLTMInProcessDefinition |
TMInProcessDefinition.xml |
インプロセス名前解決(論理名→assembly/class) |
FxXMLTMProtocolDefinition |
TMProtocolDefinition.xml |
プロトコル/URL/タイムアウト/プロパティ |
読み込み順は 埋め込みリソース → 物理ファイル → 未設定なら空 XML(OFF 扱い)→ それ以外はエラー。
パスには %ENV% 形式の環境変数を展開できる(CONFIGURATION.md 5 節)。
| 分類 | 代表的なキー | 読む側 |
|---|---|---|
| 画面制御(Web Forms) | FxSessionTimeOutCheck FxDoubleTransmissionCheck FxScreenTransitionMode FxErrorScreenPath FxPrefixOf* |
Framework の P 層 |
| DB | FxSqlCacheSwitch FxSqlCommandTimeout FxSqlTraceLog / sqlTextFilePath / ConnectionString_* |
Public/Db・MyBaseDao |
| ログ | FxLog4NetConfFile / LogLib("nlog" で NLog、既定は log4net) |
Public/Log |
| 国際化 | FxExceptionMessageCulture FxBusinessMessageCulture |
Framework |
| 実行環境 | FxContainerization(true のとき環境変数を appSettings より優先) |
GetConfigParameter(CONFIGURATION.md 4-2) |
_3TierEngine |
MethodNameHeaderS/FooterS MethodLabel_* UpdateParamHeader/Footer LikeParamHeader/Footer |
Business(net48) |
キーの全量は各サンプルの app.config / appsettings.json を見る。 本表は目安である。
Public/Util/GetConfigParameter.cs に集約。.NET では使用前に GetConfigParameter.InitConfiguration(...) が必須
(呼ばないと NOT_INITIALIZED の ArgumentException。例外を握る API では黙って false になる)。オーバーロードと、初期化前に読みに来る部品は
Public/ANALYSIS.md 6.1 節。
| 系統 | csproj 命名 | TFM |
|---|---|---|
| .NET Framework | *_net48.csproj / *_net48.sln |
v4.8(旧形式 csproj) |
| .NET | *_netcore100.csproj / *_netcore100.sln |
net10.0(SDK 形式) |
| リッチクライアント (.NET) | 同上 | net10.0-windows7.0 |
出力先は Infrastructure/Build_net48/ と Infrastructure/Build_netcore100/net10.0/(.gitignore 対象。
詳細は Infrastructure/ANALYSIS.md 5 節)。
| シンボル | 定義のされ方 | 意味 |
|---|---|---|
NETCOREAPP |
.NET SDK が net10.0 に暗黙定義(csproj の記述に依存しない) | 「.NET (Core) ビルド」=実質「非 net48」 |
NETSTD |
Framework / Public.Security / Dam* の DefineConstants に明示 |
歴史的経緯(下記) |
NET48 |
net48 側 | .NET Framework 固有 |
NETCOREAPP2_0 |
旧コード内に残存 | 実質デッド分岐 |
PERFORMANCE_LOG_SWITCH |
任意 | 性能ログ |
かつては .NET Standard でビルドされるライブラリと .NET Core でビルドされるライブラリが
併存しており、その区別が NETSTD / NETCOREAPP だった。
現在は .NET Standard 版が全て .NET Core(net10.0)に統一されたため、この区別は意味を失っている。
NETCOREAPP は .NET SDK が net10.0 ターゲットに自動的に定義する暗黙シンボルであり、
<DefineConstants> に書かれていなくても 全 netcore100 プロジェクトで真になる
(同条件の最小プロジェクトを作って #warning で確認済み)。
| プロジェクト | NETCOREAPP |
NETSTD |
|---|---|---|
Public / Business / Business.RichClient / CustomControl.RichClient / Framework.RichClient |
✓(暗黙) | ✗ |
Framework / Public.Security / Dam* |
✓(暗黙) | ✓(明示) |
| net48 の全プロジェクト | ✗ | ✗ |
したがって現状は次が成り立つ。
#if NETCOREAPP… netcore100 ビルドで常に真。#if (NETSTD || NETCOREAPP)…#if NETCOREAPPと完全に等価。#if NETSTD…NETSTDを明示定義した 3 系統でのみ真。それ以外では偽になる。
NETSTD を明示していないプロジェクト(Public / Business / *.RichClient)の中で
素の #if NETSTD を書くと、黙って net48 側の分岐に落ちる。
実測では該当箇所は 0 件(下表のとおり、書き分けは現状すべて正しい)だが、コード追加時の落とし穴になる。
| プロジェクト | (NETSTD || NETCOREAPP) |
NETSTD 単独 |
NETCOREAPP 単独 |
|---|---|---|---|
Public |
36 | 0 | 2 |
Public.Security |
0 | 83 | 0 |
Framework |
21 | 8 | 1 |
Framework.RichClient |
0 | 0 | 1 |
Business |
0 | 0 | 6 |
Business.RichClient |
0 | 0 | 4 |
CustomControl.RichClient |
0 | 0 | 27 |
整理の余地: 上記のとおり 3 つの書き方はすべて
NETCOREAPP(=非 net48)と等価に帰着する。<DefineConstants>からNETSTDを削除し、#if NETSTD/#if (NETSTD || NETCOREAPP)を#if NETCOREAPPに統一すれば、このシンボル体系は 1 本化できる(対象 約 150 箇所)。 機械的だが影響範囲が広いため、実施は別途判断。
SDK 形式 csproj はワイルドカード込みなので、プラットフォーム非対応ファイルを Compile Remove で明示的に外している。
新規ファイルを追加すると net10.0 側に自動で含まれてしまうため、Windows 専用 API を使う場合は
Compile Remove の追加が必要。逆に旧形式(net48)は列挙なので、書き足さないと入らない。
外しているファイルの一覧は、各下位文書の「TFM 差」の節にある
(Public 3 節 / Public.Security 3 節 /
Framework 10 節 / Business 6 節)。
→ _3TierEngine と MyBaseLogic は net48 専用。.NET (Core) 側で使うのは MyFcBaseLogic 系。
- ASP.NET Web Forms 一式(
BaseController、CustomControl/) CallControllerのリモート プロトコル(FxEnum.TmProtocolは .NET (Core) ではInProcessのみ): ASP.NET WS / WCF-HTTP / WCF-TCP / ASP.NET WebAPI(JSON-RPC) (Framework/ANALYSIS.md3.2 節)ServiceInterface/(WCF ホスト、ASP.NET WebAPI ホスト。Infrastructure/ANALYSIS.md7 節)
検証としてのビルドの手順(1_BuildAll.ps1、判定基準、既知のエラー)は BUILDING.md が一次情報。
本節は、その下にある bat の構成と、ビルド順・バージョン管理の仕組みを扱う。
root/programs/CS/ 直下の連番 .bat をダブルクリック実行する運用(_Please run with a double-click...txt)。
| bat | 内容 |
|---|---|
1_DeleteDir.bat / 1_DeleteFile.bat |
生成物の削除 |
2_Build_NuGet_net48.bat / 2_Build_NuGet_netcore100.bat |
Nuget_*.sln + Nuget_RichClient_*.sln をビルド(=部品) |
3_Build_Business_*.bat / 3_Build_BusinessRichClient_*.bat |
テンプレート(Business / CustomControl 系) |
4_Build_CopyAssemblies.bat |
Build_net48\ → Build\ の複写(7.1 節) |
4_Build_Framework_Tool.bat / 4_Build_Framework_ToolCore.bat |
ツール |
5_Build_*_sample.bat / 5_Build_*Core_sample.bat |
サンプル(2CS / Bat / CLI) |
6_Build_WSSrv*_sample.bat |
WSServer_sample をビルドし WS_sample\Build\ へ複写(続けてサンプルの ASPNETWebService) |
7_Build_Framework_WS.bat |
ServiceInterface(基盤側のホスト。WS_sample\Build\ を参照するので 6_ の後) |
7_Build_Framework_WSCore.bat |
何もしない(net10.0 にホストが無い。1_BuildAll.ps1 の段を残すための空の手順) |
8_Build_WSClnt*_sample.bat |
WS クライアント |
10_Build_WebApp*_sample.bat |
Web アプリのサンプル |
y_Build_Test*.bat |
テスト |
0_ExecAllBat.bat |
全実行 |
0_Release4Nuget.bat |
NuGet パッケージ用のビルド(NuGet/README.md) |
z_Common.bat / z_Common2.bat |
ビルド ツールのパス解決(各 bat が冒頭で call する) |
サンプル側の bat の詳細は Samples/ANALYSIS.md 8 節と
Samples4NetCore/ANALYSIS.md 6 節。
.NET (Core) 側は dotnet restore → dotnet msbuild を呼ぶだけなので、
エージェントは bat を経由せず直接 dotnet build "Frameworks\Infrastructure\Nuget_netcore100.sln" してよい。
net48 側は MSBuild / devenv が必要(Windows + VS 前提)。
両者は %BUILDFILEPATH%(ビルド ツールのパス)と %COMMANDLINE%(ビルド引数)という
同じインターフェイスを提供する差し替え可能な対であり、呼び出し側の bat は
call するファイルを変えるだけでビルド ツールを切り替えられる設計になっている。
| ビルド ツール | %COMMANDLINE% |
|
|---|---|---|
z_Common.bat |
MSBuild.exe | /p:Configuration=<構成> /p:DebugType=<型> /p:ContinuousIntegrationBuild=<真偽> /p:DeterministicSourcePaths=<真偽> -v:d |
z_Common2.bat |
devenv.com / devenv.exe | /build <構成>(devenv 構文) |
z_Common.bat の次の 2 つは、呼び出し側が先に設定していればその値を尊重する(#531)。
NuGet パッケージ用のビルド(0_Release4Nuget.bat)だけが既定と異なる値を渡す。
| 変数 | 既定 | 0_Release4Nuget.bat |
目的 |
|---|---|---|---|
DEBUG_TYPE |
full |
portable |
.snupkg は portable PDB でなければ受け付けられない |
CI_BUILD |
false |
true |
PDB のソース パスを /_/... に正規化する |
CI_BUILD は ContinuousIntegrationBuild と DeterministicSourcePaths の
両方に渡している。前者から後者への変換は Microsoft.NET.Sdk のターゲットが
行うため、旧形式 csproj には効かない(Source Link の自動組み込みが効かないのと
同じ構図。渡さないと net48 側だけ絶対パスのまま残る)。
以前は z_Common.bat を手で書き換えて戻す運用だった。
戻し忘れると full のまま公開してしまうため、呼び出し側から渡す形にした。
ContinuousIntegrationBuild を有効にすると、PDB にビルドしたマシンの
ローカル パスが残らない。これは体裁の問題ではない。Visual Studio は
PDB のパスにファイルが在れば、それを開くため、絶対パスのままだと
ビルドしたマシンでは Source Link を通らず、動作確認にならない。
詳細は NuGet/README.md。
z_Common2.bat は、MSBuild.exe ではエラーになるが devenv.com では通る、というケースが
散在していた時期に、ビルド ツールを devenv へ差し替えるために用意されたもの。
現在はどの bat からも呼ばれておらず、変数定義にも不具合が残っているため、そのままでは動作しない
(詳細はファイル冒頭のコメント参照)。通常は z_Common.bat を使う。
z_Common.bat は vswhere で MSBuild を解決し、見つからなければ明示エラーで停止する
(固定パス群はフォールバックとして存置)。エディションに依存しない。
Public → Public.Security → Framework → Business → Tools / Tests / Samples
部品(2_)→ テンプレート(3_)の順は、HintPath 参照による制約である。
Business 系は Nuget_*.sln の出力 DLL を拾うだけなので、Framework を直して 3_ だけを回しても変更は入らない
(Infrastructure/ANALYSIS.md 4.2 節)。
4_Build_CopyAssemblies.bat(Build_net48 → Build\ の xcopy)を飛ばすと、
net48 のサンプルとツールが一切ビルドできない。
Frameworks\Infrastructure\Build\ を HintPath 参照するプロジェクトが CS/VB 合わせて 46 件あるため
(2026-10-17 の実測。net48 のサンプル CS 20・VB 18、Tools 3、Tests 3、ServiceInterface 2)。
0_ExecAllBat.bat が 2_/3_ → 4_CopyAssemblies → 5_〜10_(サンプル)の順で呼ぶのはこのため。
Build\ に入るのは net48 の成果物のみで、.NET (Core) 側に相当物は無い
(Samples4NetCore は Build_netcore100\net10.0\ を直接参照する)。この非対称は設計どおり。
ServiceInterface(7_)はサンプルの WS_sample\Build\(6_)に依存する。 基盤側のホストが
サンプルのビルド結果を参照している(Infrastructure/ANALYSIS.md 7 節)。
Infrastructure/Directory.Build.props の OpenTouryoVersion が唯一の定義箇所。
<PropertyGroup>
<OpenTouryoVersion>3.3.0-alpha1</OpenTouryoVersion> <!-- 2026-10-17 時点の値 -->
<Company>Hitachi Solutions</Company>
</PropertyGroup>手で書き換えない。 0_SetVersion.ps1 が、ここと net48 の AssemblyInfo.cs を一括で書き換える(手順は RELEASE.md フェーズ 0)。
| 反映先 | 仕組み |
|---|---|
| SDK 形式アセンブリ(7 個) | 各 csproj の <Version>$(OpenTouryoVersion)</Version> |
| NuGet パッケージ | nuspec は <version>$version$</version> と <dependency id="Touryo.Infrastructure.*" version="$version$" />。_NuGetPack.bat が props から値を読み nuget pack -Properties version=... で渡す |
- 旧形式 csproj(
*_net48.csproj)には効かない。Microsoft.Common.propsをインポートしないため。 net48 のバージョンは各プロジェクトのProperties\AssemblyInfo.csが持つ。 Business系は 1.0.0 で別系統。Business/Properties/AssemblyInfo.csがAssemblyVersion("1.0.0.0")であり、 Public / Framework / Public.Security の版(OpenTouryoVersionに追随する)とは意図的に分けている。 そのためDirectory.Build.propsでは<Version>を全体に設定せず、OpenTouryoVersionという独自プロパティをパッケージ対象の 7 プロジェクトだけが参照する形にしている。
注意:
Directory.Build.propsの XML コメント内にハイフン 2 個の連続(--)を書くと XML として不正になり、MSBuild がプロジェクトの読み込みに失敗する。区切り線に使わないこと。
root/programs/CS/NuGet/(*.nuspec + _NuGetPack.bat、in/ に DLL を staging)。
手順は NuGet/README.md を参照。
- nuspec の
<dependencies>は csproj のPackageReferenceと一致させる(余分・不足・版ズレなし)。 依存を増減したら nuspec 側も合わせること。 - パッケージ自身と
Touryo.Infrastructure.*の相互依存のバージョンは$version$トークンで自動追随する(7.2 節)。 Symbol_Framework.RichClient.nuspecのみ、net10.0-windows7.0ビルドをlib\net10.0に配置している(12 節 14)。
CODING.md に移した(root/programs/CODING.md)。
ファイル ヘッダの書式と更新者名、ArgumentException 系の引数の順、
.bat / .ps1 の文字コードは、いずれもそちらが一次情報である。
root/programs/ 配下に共通で効く規約であり、
本書(Frameworks の分析)に置くと他領域から参照しにくいため分離した。
CODING.md の節 |
|
|---|---|
| ファイル ヘッダ(新規と既存で書式が違う) | 1 |
| その他の規約(コメント・リソース・命名) | 2 |
| 引数を検査する例外 | 3 |
| bat ファイルの文字コード | 4 |
| ps1 の文字コードと PowerShell 5.1 / 7 の両対応 | 5 |
| 名前空間 | 主なクラス |
|---|---|
Public.Db |
BaseDam SQLUtility DbEnum Dam* |
Public.Dto |
DTTable/DTRow/DTColumn(マーシャリング可能な自前 DataTable)、DataToPoco PocoToPoco DataToDictionary |
Public.Str |
CustomEncode(Base64/Hex/URL) StringChecker FormatChecker StringConverter FormatConverter CheckCharCode JIS2k4Checker |
Public.Security |
共通鍵・公開鍵暗号、ハッシュ、署名、Jwt/(JWS・JWE・JWK)、Aead/、KeyExg/、Pwd/(Public/Security/ANALYSIS.md) |
Public.Log |
LogIF(静的 façade)。ロガー名は慣習的に "ACCESS" と "SQLTRACE"。バックエンドは LogLib 設定で log4net / NLog |
Public.Reflection |
Latebind(フレームワークの動的呼び出しの心臓部)、MyAssemblies |
Public.FastReflection |
AccessorCacher CompiledExpressionCreater InstanceCreator<T> EnumToString*Extensions |
Public.IO |
ResourceLoader EmbeddedResourceLoader DeflateCompression ExponentialBackoff ZipperV2/UnZipperV2 |
Public.Util |
GetConfigParameter PerformanceRecorder RandomValueGenerator EnvInfo PubCmnFunction |
Public.Diagnostics |
MyDebug(OutputDebugAndConsole)ObjectInspector StackFrameOperator |
Public.Win32 / WinProc |
P/Invoke 群(net48 のみ) |
各名前空間の中身と落とし穴は Public/ANALYSIS.md。
Framework/ANALYSIS.md 8 節に移した。 比較的新しく、直近も更新されている領域(#600〜#606)。
| 内容 | 節 |
|---|---|
OAuth2AndOIDCClient(すべて static async Task<string>)、CmnClientParams(SpRp_*)はクライアント役の設定であること |
8.1 |
トークンの検証(CmnJwtToken / IdToken / AccessToken の aud の扱い、相手の値を受けるオーバーロード) |
8.2 |
SAML2(相手ごとの証明書と署名鍵、SigAlg、VerifyRedirect の 2 つの版) |
8.3 |
既存の版のシグネチャを変えず、オーバーロードを足すという方針が、この領域の変更すべてに通っている
(ビルド済みの呼び出し元が MissingMethodException で落ちるため)。
版は csproj を直接見ること。 Dependabot と #610 の運用で随時変わるため、本書には版を書かない。
| プロジェクト | パッケージ | 一次情報 |
|---|---|---|
| Public | log4net NLog Microsoft.Data.SqlClient System.Data.Odbc Microsoft.Extensions.Configuration* Newtonsoft.Json SharpZipLib Zipangu、推移的依存を引き上げる System.Security.Cryptography.Pkcs |
Public/ANALYSIS.md 9 節 |
| Public.Security | BouncyCastle.NetCore System.Security.Cryptography.Xml Newtonsoft.Json |
Public/Security/ANALYSIS.md 7 節 |
| Framework | Microsoft.AspNetCore.{Http,Http.Extensions,Mvc,Session} Microsoft.Extensions.PlatformAbstractions |
Framework/ANALYSIS.md 10 節 |
| Business | Microsoft.AspNetCore.Authentication{,.Cookies} Microsoft.AspNetCore.{Http,Mvc} System.Security.Cryptography.Xml Newtonsoft.Json ほか |
Business/ANALYSIS.md 6 節 |
jose-jwt は部品の依存ではない(Tests/Golden/EncAndDecUtilCUI が相互運用の確認相手として参照する)。
注意 1: Microsoft.AspNetCore.* は 2.3.0(互換シム パッケージ) を使い続けている。
net10.0 のフレームワーク参照(Microsoft.AspNetCore.App)ではない。安易に上げると壊れる可能性が高い。
注意 2: System.Security.Cryptography.Xml は 4 箇所すべてを同じ版で揃えること。
Dependabot が 1 プロジェクトずつしか上げないため、放っておくと版が割れて NU1903 が残る(12 節 11)。
注意 3: 部品の依存を上げたら、HintPath で部品を拾うサンプル(Samples4NetCore)の csproj と、
net48 の packages.config・bindingRedirect も見る(ComparePackage.ps1 / CompareRedirect.ps1。
Samples4NetCore/Legacy/ANALYSIS.md 6 節)。
脆弱性の警告を見つけたときの扱いは AGENTS.md「依存パッケージの脆弱性を見つけたら」と BUILDING.md 13 節。
領域をまたぐもの、または経緯として残すものを置く。 各アセンブリに閉じた落とし穴は、下位文書の「落とし穴」の節にある。 番号は他の文書から参照されているので、詰めずに残す。
-
4_Build_CopyAssemblies.batを飛ばすと net48 のサンプル・ツールが全滅する(7.1 節)。 -
Compile Removeを忘れると .NET (Core) ビルドが壊れる(6.3 節)。 -
CmnDaoはnewによる隠蔽であって override ではない。BaseDao型変数経由で呼ぶと親の実装が走る。 -
ReturnValueを設定し忘れると戻り値が null になる(3.2 節)。例外時も同様。 -
_damsディクショナリと_damの二重管理。Commit/Rollback/Close は両方に対して行われる。 複数 DB を使う場合はSetDam(key, dam)を使い、GetDam(key)で取り出す。 -
BaseController.cs(Web Forms)とBaseDam.csは巨大。 変更時は該当#regionに閉じた修正に留め、全体リファクタは避ける(互換性維持が最優先の設計)。 -
VB 版ミラーが存在:
root/programs/VB/Frameworks/Infrastructure/にBusiness/CustomControl/ServiceInterfaceの VB.NET 版がある(Public/Frameworkは C# 版を共有)。 Business 層テンプレートの仕様を変えると VB 側も追随が必要(Infrastructure/ANALYSIS.md8 節)。 -
生成物は
.gitignore済み。Build*/とServiceInterface/*/dll/、テストが出力先に作る*.cerは、git statusに出ない(2026-10-17 の実測で未追跡は 0 件)。出てきたら、それは新しい生成物か残骸なので、コミットせずに報告する。 -
Public/Security/MyDebug.csはPublic/Diagnostics/MyDebug.csの派生クラス(重複ではない。 アセンブリ分割の都合)。 -
TMProtocolDefinition2.xmlなど「2」付きの定義ファイルが並存する。用途は用例違い。 -
System.Security.Cryptography.Xmlは参照している 4 箇所を同じ版で揃える(NU1903 / 高、2026/08/08 に一度解消)。 Dependabot は 1 プロジェクトずつしか上げない。 #507 がPublic.Securityだけを 上げ、#510 がテスト プロジェクトだけを上げたため、一時 4 箇所が 3 通りの版に割れていた(84 警告)。 セキュリティ更新は、Dependabot の PR を取り込んだら他の参照も揃えること。 揃えておけば「もう脆弱でない」ため、同じ箇所への PR が後から来て競合することも無い (運用はBUILDING.md9 節)。 4 箇所と、net48 がこのパッケージを参照しない(BCL を使う)ことはPublic/Security/ANALYSIS.md7 節。 -
結果ファイル比較のテストは、検算しないと不具合を「正」として固定する。 実例が 2 つある。
ArrayOperator.GetLongFromByteが 3 byte 目から誤った値を返していた(#522。Public/ANALYSIS.md10 節)。EncAndDecUtilCUIが ES384 / ES512 のVerifyをFalseで記録していた(#595。Public/Security/ANALYSIS.md3.1 節)。 期待値を作るときは、出力をそのまま貼らず実装から検算し、境界を跨いだケースを置く。Verifyの期待値がFalseなら、それが仕様か不具合かを確かめること (Tests/Golden/TestCode/README.md)。 -
Public/IOに、ビルド対象外の旧 ZIP 部品が残っている。ZipBase.cs/Zipper.cs/UnZipper.csは DotNetZip(非推奨・既知脆弱性GHSA-xhg6-9j5j-w4vf)に依存しており、net48 / netcore100 の両方で除外してある。- net48 … 列挙形式のため
<Compile>に載っていない - netcore100 …
<Compile Remove="IO\Zipper.cs" />等で明示的に除外
現役は
ZipperV2/UnZipperV2(SharpZipLib、#524)。 旧ファイルを直しても何も起きない。触るなら V2 の方。 I/F 互換は無いが、引数の並びと名前、列挙体のメンバ名は旧に合わせてある。 自己解凍書庫・選択条件の文字列・StatusMSGは落とした(代替はExtractedFiles)。 ビルド対象外のファイルは他にもある(Infrastructure/ANALYSIS.md6 節)。 - net48 … 列挙形式のため
-
Symbol_Framework.RichClient.nuspecの lib TFM が不正確。net10.0-windows7.0ビルドをlib\net10.0に配置している。本来はlib\net10.0-windowsが正しく、 現状は Linux 上の net10.0 消費者も解決してしまう。直すとパッケージ解決セマンティクスが変わるため据え置き。 -
オーバーロードへの委譲で引数を落とすと、自分自身を呼んでもコンパイルが通る(警告も出ない)。
SymmetricCryptography.GenerateKeyFromPasswordで、EncryptString/DecryptStringがStackOverflowExceptionでプロセスごと落ちていた(catchできない。#608)。 呼ばれないコードは結果ファイルに現れない。 経緯と、鍵の導出を変えてはいけない理由はPublic/Security/ANALYSIS.md6 節。
| パス | 内容 | 文書 |
|---|---|---|
Samples/ |
net48 版サンプル(Web Forms / MVC5 / 2 層 C/S / バッチ / WS) | Samples/ANALYSIS.md |
Samples4NetCore/Backend/ |
.NET 10 版の Web アプリ(MVC_Sample / ASPNETWebService) |
Samples4NetCore/ANALYSIS.md |
Samples4NetCore/Legacy/ |
上記 net48 版の .NET 10 移植 | 同上 |
典型的な B層実装は Samples/Bat_sample/SimpleBatch_sample/Business/LayerB.cs(MyFcBaseLogic 継承)。
「テンプレ」#region に UOC_メソッド名 という雛形がそのまま残っているのが本フレームワークの流儀。
-
AGENTS.mdのポリシー遵守(git 操作をしない) - 作業対象の下位文書(1 節の案内表)の「落とし穴」と「作業チェックリスト」を読む
- 変更対象が net48 / netcore100 / 両方のどれか判定(
Compile Removeを確認) - 条件コンパイルは
#if NETCOREAPP(=非 net48)を使う。#if NETSTDはFramework/Public.Security/Dam*でしか真にならないので新規には使わない(6.2 節) - 新規 .cs にはヘッダ コメント(Apache License / クラス名・日本語名・更新履歴)を付与。
Copyright ブロックは新規には付けない(
CODING.md1 節) - 既存 .cs 変更時は更新履歴に 1 行追記
- public/protected メンバに日本語
<summary>を付与(DocumentationFile 出力のため) - 文字列リテラルは
FxLiteral/MyLiteral/PubLiteralに定数として追加 - ビルド確認:
dotnet build Frameworks/Infrastructure/Nuget_netcore100.sln(net48 は MSBuild 必須) - テスト実行前に フレームワークを先にビルド(
Build_netcore100/net10.0/*.dllを HintPath 参照するため) - Business 層テンプレートを変えたら VB 版ミラーの追随要否を報告