C# 使用反射访问嵌套结构的成员
我正在使用 C# 反射来实现允许用户访问内部程序变量的脚本语言。
它适用于简单的构造,但是当我尝试访问实例化结构中的数据时,它总是给出 0 作为数据值。 我的测试程序:
using System;
using System.Reflection;
namespace ConsoleApp5
{
public class TST // Test class
{
public struct S1_t
{
public UInt32 one;
public UInt32 two;
}
public S1_t t1 = new S1_t();
public UInt32 x;
public TST()
{
t1.one = 6977;
t1.two = 2;
x = 7769;
}
}
public class NFC
{
public TST tst = new TST();
}
public class PRD
{
public NFC nfc = new NFC();
}
class Program
{
private static bool GetFullVarString(Type root, string[] varNamePath, out string valStr, int index = 0)
{
Object targetObj;
bool status = false;
if (index >= varNamePath.Length) // Guard
{
valStr = "";
return false;
}
targetObj = Activator.CreateInstance(root);
string varValStr = "";
try
{
foreach (MemberInfo member in root.GetMembers()) // BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic))
{
if (member.Name != varNamePath[index])
continue;
/* Have we found the variable we're looking for? */
if (member.MemberType == MemberTypes.Field)
{
FieldInfo fieldInfo = ((FieldInfo)member);
if (fieldInfo.GetValue(targetObj) != null)
{
var miVal = fieldInfo.GetValue(targetObj);
Console.WriteLine(String.Format(" Field Type: {0}", fieldInfo.FieldType.ToString()));
Type thisType = Type.GetType(fieldInfo.FieldType.FullName.ToString());
Boolean isStruct = thisType.IsValueType && !thisType.IsEnum &&
!(fieldInfo.FieldType.ToString().StartsWith("System"));
Console.WriteLine(String.Format(" IsStruct: {0}", isStruct.ToString()));
if (fieldInfo.FieldType.IsClass)
{
/* We've found a child class, so we need to change
* the root type and step into it.
*/
Type newType = Type.GetType(fieldInfo.FieldType.FullName.ToString());
status = GetFullVarString(newType, varNamePath, out varValStr, index + 1);
}
else if (isStruct)
{
/* We've found a child struct, so we need to change
* the root type and step into it.
*/
Type newType = Type.GetType(fieldInfo.FieldType.FullName.ToString());
status = GetFullVarString(newType, varNamePath, out varValStr, index + 1);
}
else
{
varValStr = miVal.ToString();
}
status = true;
break;
}
}
else if (member.MemberType == MemberTypes.NestedType)
{
Type nestedType = (Type)member; // MemberInfo that is a NestedType is just a Type itself
status = GetFullVarString(nestedType, varNamePath, out varValStr, index + 1);
}
}
}
catch (Exception ex)
{
Console.WriteLine(String.Format("Exception: {0}", ex.Message));
status = false;
}
valStr = varValStr;
return status;
}
static void Main(string[] args)
{
PRD prd = new PRD();
string fullVar, tstr;
Type root = typeof(PRD);
fullVar = "nfc.tst.x";
GetFullVarString(root, fullVar.Split('.'), out tstr);
Console.WriteLine(String.Format("{0} = {1}", fullVar, tstr));
fullVar = "nfc.tst.t1.one";
GetFullVarString(root, fullVar.Split('.'), out tstr);
Console.WriteLine(String.Format("{0} = {1}", fullVar, tstr));
Console.ReadKey();
}
}
}
输出显示 TST 类底部的变量“x”显示正常,但 t1 结构的成员则不然。
Field Type: ConsoleApp5.NFC
IsStruct: False
Field Type: ConsoleApp5.TST
IsStruct: False
Field Type: System.UInt32
IsStruct: False
nfc.tst.x = 7769
Field Type: ConsoleApp5.NFC
IsStruct: False
Field Type: ConsoleApp5.TST
IsStruct: False
Field Type: ConsoleApp5.TST+S1_t
IsStruct: True
Field Type: System.UInt32
IsStruct: False
nfc.tst.t1.one = 0
我想这可能与在非类结构上使用 Activator 类有关,但我不知道。
有什么帮助吗?
I am using C# reflection to implement a scripting language that allows the user to have access to internal program variables.
It works for simple constructs, but when I try to access data in instantiated structures, it always gives 0 as the data value.
My test program:
using System;
using System.Reflection;
namespace ConsoleApp5
{
public class TST // Test class
{
public struct S1_t
{
public UInt32 one;
public UInt32 two;
}
public S1_t t1 = new S1_t();
public UInt32 x;
public TST()
{
t1.one = 6977;
t1.two = 2;
x = 7769;
}
}
public class NFC
{
public TST tst = new TST();
}
public class PRD
{
public NFC nfc = new NFC();
}
class Program
{
private static bool GetFullVarString(Type root, string[] varNamePath, out string valStr, int index = 0)
{
Object targetObj;
bool status = false;
if (index >= varNamePath.Length) // Guard
{
valStr = "";
return false;
}
targetObj = Activator.CreateInstance(root);
string varValStr = "";
try
{
foreach (MemberInfo member in root.GetMembers()) // BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic))
{
if (member.Name != varNamePath[index])
continue;
/* Have we found the variable we're looking for? */
if (member.MemberType == MemberTypes.Field)
{
FieldInfo fieldInfo = ((FieldInfo)member);
if (fieldInfo.GetValue(targetObj) != null)
{
var miVal = fieldInfo.GetValue(targetObj);
Console.WriteLine(String.Format(" Field Type: {0}", fieldInfo.FieldType.ToString()));
Type thisType = Type.GetType(fieldInfo.FieldType.FullName.ToString());
Boolean isStruct = thisType.IsValueType && !thisType.IsEnum &&
!(fieldInfo.FieldType.ToString().StartsWith("System"));
Console.WriteLine(String.Format(" IsStruct: {0}", isStruct.ToString()));
if (fieldInfo.FieldType.IsClass)
{
/* We've found a child class, so we need to change
* the root type and step into it.
*/
Type newType = Type.GetType(fieldInfo.FieldType.FullName.ToString());
status = GetFullVarString(newType, varNamePath, out varValStr, index + 1);
}
else if (isStruct)
{
/* We've found a child struct, so we need to change
* the root type and step into it.
*/
Type newType = Type.GetType(fieldInfo.FieldType.FullName.ToString());
status = GetFullVarString(newType, varNamePath, out varValStr, index + 1);
}
else
{
varValStr = miVal.ToString();
}
status = true;
break;
}
}
else if (member.MemberType == MemberTypes.NestedType)
{
Type nestedType = (Type)member; // MemberInfo that is a NestedType is just a Type itself
status = GetFullVarString(nestedType, varNamePath, out varValStr, index + 1);
}
}
}
catch (Exception ex)
{
Console.WriteLine(String.Format("Exception: {0}", ex.Message));
status = false;
}
valStr = varValStr;
return status;
}
static void Main(string[] args)
{
PRD prd = new PRD();
string fullVar, tstr;
Type root = typeof(PRD);
fullVar = "nfc.tst.x";
GetFullVarString(root, fullVar.Split('.'), out tstr);
Console.WriteLine(String.Format("{0} = {1}", fullVar, tstr));
fullVar = "nfc.tst.t1.one";
GetFullVarString(root, fullVar.Split('.'), out tstr);
Console.WriteLine(String.Format("{0} = {1}", fullVar, tstr));
Console.ReadKey();
}
}
}
The output shows that the variable 'x' at the base of the TST class displays fine, but the member of the t1 structure does not.
Field Type: ConsoleApp5.NFC
IsStruct: False
Field Type: ConsoleApp5.TST
IsStruct: False
Field Type: System.UInt32
IsStruct: False
nfc.tst.x = 7769
Field Type: ConsoleApp5.NFC
IsStruct: False
Field Type: ConsoleApp5.TST
IsStruct: False
Field Type: ConsoleApp5.TST+S1_t
IsStruct: True
Field Type: System.UInt32
IsStruct: False
nfc.tst.t1.one = 0
I'm thinking that maybe it has to do with using the Activator class on the non-class structure, but I have no idea.
Any help??
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论