teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

5

少し修正

2020/05/08 07:45

投稿

退会済みユーザー
answer CHANGED
@@ -1,6 +1,6 @@
1
1
  ~~そもそもbyteはbyteでクラスではないので変換できません。バイト値を判定し、それに対応したクラスをnewして返せば良いと思います。~~
2
2
 
3
- はまってるのはジェネリック型指定の辺りだと思うので、ジェネリック型をやめてみたらどうでしょう。ジェネリック型はコンパイル時点で型を決定する必要があります。また、
3
+ はまってるのはジェネリック型指定の辺りだと思うので、ジェネリック型をやめてみたらどうでしょう。ジェネリック型はコンパイル時点で型を決定する必要があります。
4
4
  こういう感じなら動くかな。
5
5
  1バイト目の値を0, 1, 2に書き換えると、違う構造体が返ってくるのが確認できます。
6
6
  補足すると、Marshal.AllocHGlobalは後方互換性のためのメモリ確保方法なので、特別な理由が無い限りはMarshal.AllocCoTaskMemかGCHandle.Allocを使用した方が良いでしょう。

4

少し修正

2020/05/08 07:45

投稿

退会済みユーザー
answer CHANGED
@@ -1,9 +1,10 @@
1
1
  ~~そもそもbyteはbyteでクラスではないので変換できません。バイト値を判定し、それに対応したクラスをnewして返せば良いと思います。~~
2
2
 
3
- はまってるのはジェネリック型指定の辺りだと思うので、ジェネリック型をやめてみたらどうでしょう。ジェネリック型はコンパイル時点で型を決定する必要があります。
3
+ はまってるのはジェネリック型指定の辺りだと思うので、ジェネリック型をやめてみたらどうでしょう。ジェネリック型はコンパイル時点で型を決定する必要があります。また、
4
4
  こういう感じなら動くかな。
5
5
  1バイト目の値を0, 1, 2に書き換えると、違う構造体が返ってくるのが確認できます。
6
6
  補足すると、Marshal.AllocHGlobalは後方互換性のためのメモリ確保方法なので、特別な理由が無い限りはMarshal.AllocCoTaskMemかGCHandle.Allocを使用した方が良いでしょう。
7
+ あと、クラスと構造体は異なるものなので、きちんと単語の使い分けをしてください。
7
8
 
8
9
  ```C#
9
10
  using System;

3

補足追加

2020/05/08 05:15

投稿

退会済みユーザー
answer CHANGED
@@ -3,6 +3,7 @@
3
3
  はまってるのはジェネリック型指定の辺りだと思うので、ジェネリック型をやめてみたらどうでしょう。ジェネリック型はコンパイル時点で型を決定する必要があります。
4
4
  こういう感じなら動くかな。
5
5
  1バイト目の値を0, 1, 2に書き換えると、違う構造体が返ってくるのが確認できます。
6
+ 補足すると、Marshal.AllocHGlobalは後方互換性のためのメモリ確保方法なので、特別な理由が無い限りはMarshal.AllocCoTaskMemかGCHandle.Allocを使用した方が良いでしょう。
6
7
 
7
8
  ```C#
8
9
  using System;

2

回答内容を質問の修正に合わせて変更

2020/05/08 04:56

投稿

退会済みユーザー
answer CHANGED
@@ -1,1 +1,81 @@
1
- そもそもbyteはbyteでクラスではないので変換できません。バイト値を判定し、それに対応したクラスをnewして返せば良いと思います。
1
+ ~~そもそもbyteはbyteでクラスではないので変換できません。バイト値を判定し、それに対応したクラスをnewして返せば良いと思います。~~
2
+
3
+ はまってるのはジェネリック型指定の辺りだと思うので、ジェネリック型をやめてみたらどうでしょう。ジェネリック型はコンパイル時点で型を決定する必要があります。
4
+ こういう感じなら動くかな。
5
+ 1バイト目の値を0, 1, 2に書き換えると、違う構造体が返ってくるのが確認できます。
6
+
7
+ ```C#
8
+ using System;
9
+ using System.Collections.Generic;
10
+ using System.Runtime.InteropServices;
11
+
12
+ namespace ConsoleApp1
13
+ {
14
+ class Program
15
+ {
16
+ public enum StructType : byte
17
+ {
18
+ AProduct = 0,
19
+ BProduct,
20
+ CProduct
21
+ }
22
+
23
+ interface IProduct { }
24
+
25
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
26
+ struct AProduct : IProduct
27
+ {
28
+ byte A;
29
+ }
30
+
31
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
32
+ struct BProduct : IProduct
33
+ {
34
+ byte A;
35
+ byte B;
36
+ }
37
+
38
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
39
+ struct CProduct : IProduct
40
+ {
41
+ byte A;
42
+ byte B;
43
+ byte C;
44
+ }
45
+
46
+ static Dictionary<StructType, Type> _DicProductType = new Dictionary<StructType, Type>()
47
+ {
48
+ {StructType.AProduct, typeof(AProduct)},
49
+ {StructType.BProduct, typeof(BProduct)},
50
+ {StructType.CProduct, typeof(CProduct)}
51
+ };
52
+
53
+ static IProduct GetProductDetail(byte[] bytes, Type type)
54
+ {
55
+ GCHandle gch = GCHandle.Alloc(bytes, GCHandleType.Pinned);
56
+ IProduct result = (IProduct)Marshal.PtrToStructure(gch.AddrOfPinnedObject(), type);
57
+ gch.Free();
58
+ return result;
59
+ }
60
+
61
+ static IProduct GetProduct(byte[] bytes)
62
+ {
63
+ StructType stype = (StructType)bytes[0];
64
+ if (!_DicProductType.ContainsKey(stype))
65
+ {
66
+ throw new NotImplementedException("Undefined Structure");
67
+ }
68
+
69
+ return GetProductDetail(bytes, _DicProductType[stype]);
70
+ }
71
+
72
+ static void Main(string[] args)
73
+ {
74
+ var bytes = new byte[] { 0x00, 0x10, 0x20 };
75
+ var product = GetProduct(bytes);
76
+ Console.WriteLine(product);
77
+ }
78
+ }
79
+ }
80
+
81
+ ```

1

少し修正

2020/05/08 04:44

投稿

退会済みユーザー
answer CHANGED
@@ -1,1 +1,1 @@
1
- そもそもbyteはbyteでクラスではないので変換できません。バイト値を判定し、クラスをnewして返せば良いと思います。
1
+ そもそもbyteはbyteでクラスではないので変換できません。バイト値を判定し、それに対応したクラスをnewして返せば良いと思います。