C++の場合
cpp
1struct SHARE_INFO_0 { 2 LPWSTR shi0_netname; 3}; 4struct SHARE_INFO_1 { 5 LPWSTR shi1_netname; 6 DWORD shi1_type; 7 LPWSTR shi1_remark; 8}; 9struct SHARE_INFO_2 { 10 LPWSTR shi1_netname; 11 DWORD shi1_type; 12 LPWSTR shi1_remark; 13 DWORD shi2_permissions; 14 DWORD shi2_max_uses; 15 DWORD shi2_current_uses; 16 LPWSTR shi2_path; 17 LPWSTR shi2_passwd; 18};
のような構造体群と値を
cpp
1template<typename ...Args> 2struct first_enabled {}; 3 4template<typename T, typename ...Args> 5struct first_enabled<std::enable_if<true, T>, Args...> { using type = T; }; 6template<typename T, typename ...Args> 7struct first_enabled<std::enable_if<false, T>, Args...>: first_enabled<Args...> {}; 8template<typename T, typename ...Args> 9struct first_enabled<T, Args...> { using type = T; }; 10 11template<typename ...Args> 12using first_enabled_t = typename first_enabled<Args...>::type; 13 14template<int InfoLevel> 15using SHARE_INFO = first_enabled_t< 16 std::enable_if<0 == InfoLevel, SHARE_INFO_0>, 17 std::enable_if<1 == InfoLevel, SHARE_INFO_1>, 18 std::enable_if<2 == InfoLevel, SHARE_INFO_2> 19>;
のようにmappingして
cpp
1template<int infoLevel> 2SHARE_INFO<infoLevel> f(){ return {};}
のようにコンパイル時に値=>型に変換できますが、
http://melpon.org/wandbox/permlink/qSNWfttreE9limQg
C#の場合こういうことはできないのでしょうか?
追記
状況としてはWin32APIをWrapしようとしています。
Win32APIのNetShareEnum関数は第二引数によって、第三引数から返されるものが変化し、
第二引数が0, 1, 2, 502の時、それぞれSHARE_INFO_0
,SHARE_INFO_1
,SHARE_INFO_2
,SHARE_INFO_502
の4つの構造体のいずれかを指すポインタを返します。
とりあえず第二引数に2を指定するものをラップしたのが
です。
csharp
1public static List<SHARE_INFO_2> NetShareEnum_2_wrap(string serverName) { 2 var re = new List <SHARE_INFO_2> { }; 3 Int32 er = 0; 4 Int32 tr = 0; 5 Int32 resume = 0; 6 int res; 7 do 8 { 9 res = NetShareEnum(serverName, 2, out var bufPtr, -1, ref er, ref tr, ref resume); 10 if (res != (int)NET_API_STATUS.NERR_Success && res != (int)NET_API_STATUS.ERROR_MORE_DATA) break; 11 var infoP = bufPtr; 12 for (int i = 0; i < er; ++i) 13 { 14 re.Add(Marshal.PtrToStructure<SHARE_INFO_2>(infoP)); 15 infoP = IntPtr.Add(infoP, Marshal.SizeOf<SHARE_INFO_2>()); 16 } 17 NetApiBufferFree(bufPtr); 18 } while (res == (int)NET_API_STATUS.ERROR_MORE_DATA); 19 return re; 20}
これを一般化するために
まずはdynamicを使うことを考えましたが、できれば静的にやりたいなと思い却下し
空のinterfaceクラスをでっち上げてSHARE_INFO_x
クラスに指定し、Genericsの制約に使用することも考えましたが、空のinterfaceクラスは良くないという記事が見つかり、またマーシャリングと組み合わせられるのかわからず断念し、
そこで上述のような静的型mapみたいなことを思いついたわけですが、C#のGenericsだと値は
渡せなかったのを思い出し、諦め、
型のmappingみたいなことをコンパイル時にやることは可能か質問したのですが、無理そうですね・・・。
一般的な実装について聞くには情報不足でした。
iwamoto_takaakiさんの提案していただいた方法はかなりトリッキーとのことですが・・・、私は好きだけどいいんだろうか、こんな設計・・・。
回答4件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2017/01/12 10:38 編集
2017/01/14 09:45