一、前言
上一章通过反射实现创建动态编辑栏,但是此时的编辑栏还并没有和结构体数据关联。本章将实现编辑栏中修改的数据将反馈到对应的结构体中,并最后通过序列化将结构体数据以文本的形式进行存储
二、实现
1、FieldInfo.SetValue方法
将给定对象的字段设置为给定值,查阅了C#的官方文档,上面的案例是这样的
using System;
using System.Reflection;
using System.Globalization;
public class Example
{
private string myString;
public Example()
{
myString = "Old value";
}
public string StringProperty
{
get
{
return myString;
}
}
}
public class FieldInfo_SetValue
{
public static void Main()
{
Example myObject = new Example();
Type myType = typeof(Example);
FieldInfo myFieldInfo = myType.GetField("myString",
BindingFlags.NonPublic | BindingFlags.Instance);
// Display the string before applying SetValue to the field.
Console.WriteLine( "\nThe field value of myString is \"{0}\".",
myFieldInfo.GetValue(myObject));
// Display the SetValue signature used to set the value of a field.
Console.WriteLine( "Applying SetValue(Object, Object).");
// Change the field value using the SetValue method.
myFieldInfo.SetValue(myObject, "New value");
// Display the string after applying SetValue to the field.
Console.WriteLine( "The field value of mystring is \"{0}\".",
myFieldInfo.GetValue(myObject));
}
}
/* This code example produces the following output:
The field value of myString is "Old value".
Applying SetValue(Object, Object).
The field value of mystring is "New value".
这段代码在参数是类的对象的时候是毫无问题的,但是传进来结构体变量的时候,就会出现没有附上值的问题。这个主要是跟结构体是值类型,类是引用类型有关。
Fieldinfo.SetValue(object,object),里面的参数都是引用类型的,而结构体是指类型,在调用该方法传结构体变量的时候,会将结构体赋值一份新的,然后在方法里面对新的值进行了修改,而传进去原来的结构体并没有任何改变。所以,在调用SetValue之前,先将结构体进行装箱操作变成Object类型的变量,然后,在进行拆箱操作,将Object变量转换成结构体变量。代码如下:
public static object SetValue_ReflectMethod<T>(T obj, string paramName, string paramValue)
{
//先装箱 变成引用类型的
object tempObj = obj;
if (obj != null)
{
try
{
Type tempType = obj.GetType();
//设置字段
FieldInfo tempFI = tempType.GetField(paramName);
tempFI.SetValue(tempObj, Convert.ChangeType(paramValue, tempFI.FieldType));
//设置属性
//PropertyInfo tempPI = tempType.GetProperty(paramName);
//tempPI.SetValue(tempObj, Convert.ChangeType(paramValue, tempPI.PropertyType), null);
}
catch (Exception e)
{
Debug.Log("编辑错误" + e.Message);
tempObj = null;
}
}
return tempObj;
}
我将这个方法进行了简单的泛型处理,这样保证不管是什么结构体或类都可以作为参数传递进来,并进行转换。方法最后,返回的是一个Object类型的变量,对这个变量进行拆箱操作就可以了:
object tempObject = SetValue_ReflectMethod(curEditorRP, name, value);
if (null == tempObject)
{
tempEditorSucced = false;
return tempEditorSucced;
}
curEditorRP = (PD_RoutePoint)tempObject;
在每一个编辑栏的输入框组建中都添加了编辑结束响应事件,保证每次对单个编辑框编辑的时候,结构体的数据都会得到修改如图所示:当对单个编辑框进行修改的时候,右侧的Inspector面板上的结构体字段的值也会相应的改变,在输入错误的时候,还加入了相应的处理,出现输入的值和字段类型不匹配则回到上一个输入框的值,并且结构体不发生改变。
最后,将修改后的结构体变量的值存成文本文件:
string tempJson = JsonUtility.ToJson(curEditorRP);
string url=M_CurProjectAssetPath+ "/ResourceData/Test.json";
try
{
FileInfo file = new FileInfo(url);
//判断有没有文件,有则打开文件,,没有创建后打开文件
StreamWriter sw = file.CreateText();
sw.WriteLine(tempJson);
//注意释放资源
sw.Close();
sw.Dispose();
}
catch (Exception e)
{
Debug.Log(e.Message);
}
三、总结
1、初步具备了根据结构体字段来动态创建编辑框的功能
2、可以在输入框中对结构体的对应名称字段进行修改,并且编辑框中还加入了错误输入的处理
3、将结构体数据保存成Json文件
4、尚不具备对泛型的处理
未完待续。。。。。