我想为SerializedObject
编写一个通用的扩展方法,可以代替FindProperty
然后访问whateverValue
成员,这样我就可以编写so.Get<Bool>("myValue")
而不是so.FindProperty("myValue").boolValue
。
如果模板专业化是C#中的一件事,我想解决这个问题:
public static T Get<T>(this SerializedObject so, string name) {
Debug.LogError("Get called with unsuported type!");
}
public static bool Get<bool>(this SerializedObject so, string name) {
return so.FindProperty(name).boolValue;
}
如何才能在适当的C#中实现这样的目标?我还尝试添加System.Type
参数而不是特化,但那么这个函数的返回类型应该是什么?
答案 0 :(得分:2)
我会使用一些函数式编程。泛型函数的输入参数之一将是另一个函数,它将定义如何读取属性:
public static T Get<T>(this SerializedObject so, string name, Func<SerializedProperty, T> getter) {
var property = so.FindProperty(name);
if (property == null) {
;//handle "not found"
}
return getter(property);
}
我将如何使用它的几个例子:
internal bool ExampleBoolValue(SerializedObject so) {
return so.Get("myBoolValue", (p => p.boolValue));
}
internal int ExampleIntValue(SerializedObject so) {
return so.Get("myIntValue", (p => p.intValue));
}
我没有在这台机器上安装Unity,所以我不确定Unity是否支持这些.NET功能。
setter方法的UPDATE :
public static void Set(this SerializedObject so, string name, Action<SerializedProperty> setter) {
var property = so.FindProperty(name);
if (property == null) {
;//handle "not found"
}
setter(property);
}
设置值的示例:
internal void SetExampleBoolValue(SerializedObject so, bool newValue) {
so.Set("myBoolValue", (p => p.boolValue = newValue));
}
internal void SetExampleIntValue(SerializedObject so, int newValue) {
so.Set("myIntValue", (p => p.intValue = newValue));
}
答案 1 :(得分:2)
你可以使用通用静态的魔力来实现这一目标。
第一个班级GetPropertyValue<T>
将根据类型存储您的处理程序。静态处理程序最初设置为“不支持”消息,但静态构造函数将调用InitGetPropertyValue类来初始化所有处理程序。因为这是在该类的静态构造函数中,所以只有在第一次初始化类时才会调用它。
由于GetPropertyValue<int>.Get
的静态变量与静态变量GetPropertyValue<string>.Get
不同,因此您之前存储的类型的处理程序将在每次后续调用时使用。
public static class MyExtensions
{
private static class GetPropertyValue<T>
{
static GetPropertyValue()
{
InitGetPropertyValue.Initialize();
}
public static Func<SerializedObject, string, T> Get = (so, name) =>
{
Debug.Print("Get called with unsupported type!");
return default(T);
};
}
private static class InitGetPropertyValue
{
static InitGetPropertyValue()
{
Debug.Print("Initializing property getters");
GetPropertyValue<int>.Get = (so, name) => (int)so.FindProperty(name) ;
GetPropertyValue<Guid>.Get = (so, name) => (Guid)so.FindProperty(name);
GetPropertyValue<string>.Get = (so, name) => so.FindProperty(name).ToString();
}
public static bool Initialize()
{
return true;
}
}
public static T Get<T>(this SerializedObject so, string name)
{
return GetPropertyValue<T>.Get(so, name);
}
}
答案 2 :(得分:1)
虽然不是一个漂亮的解决方案,但一个工作的解决方案就像:
public static T Get<T>(this SerializedObject so, string name) {
if (typeof(T) == typeof(bool){
return (T)(object)so.FindProperty(name).boolValue;
}
else if {
...
}
else {
Debug.LogError("Get called with unsuported type!");
}
}
我个人也喜欢这样:
public static bool GetBoolean(this SerializedObject so, string name)
public static int GetInt(this SerializedObject so, string name)
语义保持不变,但实现更清晰。