【发布时间】:2014-10-24 07:14:03
【问题描述】:
我有一个 TileType[][] 类型的 fieldInfo。如何为这个 fieldInfo 设置值?
internal static class Program
{
private struct Data
{
public enum TileType : byte
{
Passable,
Unpassable
}
public TileType[][] TileTypes;
}
private static T LoadData<T>(string[] values)
{
var t = (T)Activator.CreateInstance(typeof(T));
object boxed = t;
FieldInfo field = boxed.GetType().GetField("TileTypes"); // I get TileType[][] field here.
IList<IList<string>> tilesMatrix = new string[values.Length][];
for (byte x = 0; x < values.Length; x++)
{
tilesMatrix[x] = new string[values.Length];
tilesMatrix[x] = values;
}
SetValuesToJaggedArray<object, byte[], byte>(boxed, field, tilesMatrix);
return (T)boxed;
}
private static void SetValuesToJaggedArray<T, TTarget, TTargetElement>(T obj, FieldInfo field, IList<IList<string>> values)
{
var objs = new Array[values.Count];
for (ushort x = 0; x < values.Count; x++)
{
var ar = new TTarget[values.Count];
var arobjs = new object[values.Count];
for (ushort y = 0; y < values.Count; y++)
{
var elements = new List<TTargetElement>();
for (ushort z = 0; z < values[y].Count; z++)
{
var element = (TTargetElement)Convert.ChangeType(values[y][z], typeof(TTargetElement), CultureInfo.InvariantCulture);
elements.Add(element);
}
object bElts = elements.ToArray();
var value = (TTarget)bElts;
arobjs[y] = value;
}
Array.Copy(arobjs, ar, values.Count);
objs[x] = new TTarget[values.Count];
Array.Copy(ar, objs[x], values.Count);
}
object b = objs;
field.SetValue(obj, b); // Exception here!
}
static void Main(string[] args)
{
Data d = LoadData<Data>(new string[4] { "0", "1", "2", "3" });
}
}
我从行 field.SetValue(obj, b); 得到异常因为我不知道如何在那里设置一个值。任何帮助表示赞赏。
已解决,感谢米奇解答:
internal static class Program
{
public struct Data
{
public enum TileType : byte
{
Passable,
Unpassable,
Water,
Empty
}
public TileType[][] TileTypes;
}
private static T LoadData<T>(string[][] values)
{
var t = (T)Activator.CreateInstance(typeof(T));
object boxed = t;
FieldInfo field = boxed.GetType().GetField("TileTypes"); // I get TileType[][] field here.
SetValuesToJaggedArray<object, byte>(boxed, field, values);
return (T)boxed;
}
private static void SetValuesToJaggedArray<T, TTargetElement>(T obj, FieldInfo field, string[][] values)
{
var objs = new TTargetElement[values.Length][];
for (ushort x = 0; x < values.Length; x++)
{
var elements = new TTargetElement[values.Length];
for (ushort y = 0; y < values.Length; y++)
{
var element = (TTargetElement)Convert.ChangeType(values[x][y], typeof(TTargetElement), CultureInfo.InvariantCulture);
elements[y] = element;
}
objs[x] = elements;
}
field.SetValue(obj, objs);
}
static void Main()
{
var matrix = new string[4][];
matrix[0] = new[] { "0", "1", "2", "3" };
matrix[1] = new[] { "1", "2", "3", "0" };
matrix[2] = new[] { "2", "3", "0", "1" };
matrix[3] = new[] { "3", "0", "1", "2" };
var d = LoadData<Data>(matrix);
const string whiteSpace = " ";
for (byte x = 0; x < d.TileTypes.Length; x++)
{
for (byte y = 0; y < d.TileTypes.Length; y++)
Console.Write(d.TileTypes[x][y] + whiteSpace);
Console.WriteLine();
}
Console.ReadKey();
}
}
【问题讨论】:
-
有什么异常?它在信息中说了什么?为什么要使用反射和泛型?为什么
Data定义为struct? -
@JeanHominal 例外是:无法将 Array[] 转换为 TileType[][]。我使用反射和泛型因为我反序列化来自文本文件的数据。 “数据”被定义为“结构”,因为我实际上不需要引用类型作为我将进一步使用的输出类型。我只会从该结构中获取数据一次,然后将其从内存中删除。
-
你不需要需要反射和泛型来反序列化。您对
struct的使用没有充分的理由,在 C# 中,struct仅在证明有好处时才使用。使用ushort和byte作为数组索引是非惯用且徒劳的,因为这些值将由[]运算符转换为int。您在矩阵的每一行中都影响了相同的values对象 - 您是否希望tilesMatrix[y] = values复制该对象?一旦将值"2"和"3"转换为TileType,您期望得到什么结果?我感觉你平时写的是C++。 -
另外,我不明白为什么当你可以直接返回
TileType[][]时返回Data结构。 -
@JeanHominal '您对结构的使用没有充分的理由,在 C# 中,只有在证明有好处时才会使用结构。'请举例:)。 'tilesMatrix[y] = values' 这些不是矩阵的实际值。因为在我的机器上使用 ushort 比使用 int 更快。
标签: c# .net reflection