我正在尝试将数据序列化到我的类中,从MonoBehaviour
派生,这些类不能从客户端代码创建(例如,使用new
关键字),而是必须由特定于Unity3D的方法GameObject.AddComponent<T>()
。如何使用YamlDotNet
框架用值填充我的类而不必为每个类创建适配器?我可以配置某种内置适配器,这样YamlDotNet不会实例化它试图序列化的类吗?
典型文件可能包含项目的映射,例如
%YAML 1.1
%TAG !invt! _PathwaysEngine.Inventory.
%TAG !intf! _PathwaysEngine.Adventure.
---
Backpack_01: !invt!Item+yml
mass: 2
desc:
nouns: /^bag|(back)?pack|sack|container$/
description: |
Your backpack is only slightly worn, and...
rand_descriptions:
- "It's flaps twirl in the breeze."
- "You stare at it. You feel enriched."
MagLite_LR05: !invt!Lamp+yml
cost: 56
mass: 2
time: 5760
desc:
nouns: /^light|flashlight|maglite|lr_05$/
description: |
On the side of this flashlight is a label...
(Type "light" to turn it on and off.)
...
如果标签是我的项目的完全指定的类名称,例如PathwaysEngine.Inventory.Lamp+yml
,PathwaysEngine
是我用于我的游戏引擎代码的命名空间,Inventory
处理项目&amp; whatnot和Lamp+yml
是编译器如何在yml
内表示嵌套类Lamp
。 Lamp+yml
可能如下所示:
public partial class Lamp : Item, IWearable {
public new class yml : Item.yml {
public float time {get;set;}
public void Deserialize(Lamp o) {
base.Deserialize((Item) o);
o.time = time;
}
}
}
我对来自Deserialize()
Thing
的所有对象发送Awake()
,即游戏中存在MonoBehaviour
类。在其他地方,我已经创建了一个非常复杂的Dictionary
,其中填充了Someclass+yml
类型的对象,然后Deserialize
获取了一个真实的运行时类Someclass
的实例并填充它有价值的。必须有一个更清洁的方法,对吧?
我怎么能:
告诉Deserializer
我的课程是什么?
请参阅第二个编辑以获得上述问题的良好解决方案
在没有尝试创建我的MonoBehaviour
派生类的情况下获取数据?
编辑:我已经解决了这个问题,并找到了处理自定义数据的好方法(在我尝试从我的数据中解析正则表达式的特殊情况下,它们不被视为字符串&amp;因此,对于正则表达式是不可转换的)是对该特定字符串使用IYamlTypeConverter
。然而,将YamlDotNet与Unity3D MonoBehaviour
一起使用仍然是一个问题。
另一个编辑:以上示例使用一种非常丑陋的方式来确定类型。在我的例子中,最好的办法是首先用反序列化器注册标签,例如,
var pre = "tag:yaml.org,2002:";
var tags = new Dictionary<string,Type> {
{ "regex", typeof(Regex) },
{ "date", typeof(DateTime) },
{ "item", typeof(Item) }};
foreach (var tag in tags)
deserializer.RegisterTagMapping(
pre+tag.Key, tag.Value);
然后,我在!!tag
文件中使用*.yml
表示法,例如,
%YAML 1.1
---
Special Item: !!item
nouns: /thing|item|object/
someBoolean: true
Start Date: !!date 2015-12-17
some regex: !!regex /matches\s+whatever/
...
答案 0 :(得分:1)
您可以将IObjectFactory
的自定义实现传递给Deserializer
类的构造函数。每次反序列化器需要创建对象的实例时,它都会使用IObjectFactory
来创建它。
请注意,您的工厂将负责创建反序列化的每个类型的实例。实现它的最简单方法是在DefaultObjectFactory
周围创建一个装饰器,例如:
class UnityObjectFactory : IObjectFactory
{
private readonly DefaultObjectFactory DefaultFactory =
new DefaultObjectFactory();
public object Create(Type type)
{
// You can use specific types manually
if (type == typeof(MyCustomType))
{
return GameObject.AddComponent<MyCustomType>();
}
// Or use a marker interface
else if (typeof(IMyMarkerInterface).IsAssignableFrom(type))
{
return typeof(GameObject)
.GetMethod("AddComponent")
.MakeGenericMethod(type)
.Invoke();
}
// Delegate unknown types to the default factory
else
{
return DefaultFactory(type);
}
}
}