※ 本記事にはプロモーションが含まれています。
こんにちは! ねこです。
Firestore(Firebase)を Unity で利用する場合。
大体は、使用しやすくするためにクラスを定義して、その中に入れると思います。
しかし、下記のようにネストされたクラスの配列は、利用できません。
[FirestoreProperty]
public string name { get; set; } // OK.
[FirestoreProperty]
public List<Dictionary<string, object>> objects { get; set; } // OK.
[FirestoreProperty]
public List<Entity> entities { get; set; } // NG.
その場合の解決方法のひとつとして、リフレクションを利用する方法があります。
ネストしたいクラス(Entity)を、リフレクションを通じて Dictonary <string, object> に変換してしまえばいいわけです。
以下、サンプルコードを記載します。
リフレクションでの処理は、他の処理と比較して重いため、例えばループなどの処理に利用する場合は、記述に気をつけてください!
サンプルコード
ObjectExtension.cs
実際の変換処理を、Extension として実装したもの。
using System;
using System.Collections.Generic;
using System.Linq;
public static class ObjectExtension
{
/// <summary>
/// Get fields of the class as Dictonary<string, object>
/// </summary>
/// <param name="obj">Target object.</param>
/// <typeparam name="T">The object type.</typeparam>
/// <returns>All the fields as dictonary.</returns>
public static Dictionary<string, object> GetFieldsAsDictonary<T>(this T obj)
{
return obj.GetType().GetFields()
.ToDictionary(pi => pi.Name, pi => pi.GetValue(obj));
}
/// <summary>
/// Convert dictionary to fields of class.
/// </summary>
/// <param name="dictionary">The dictionary before change.</param>
/// <typeparam name="T">The class after change.</typeparam>
/// <returns>The class object.</returns>
public static T ConvertClassFields<T>(this Dictionary<string, object> dictionary) where T : new()
{
T obj = new T();
var fields = obj.GetType().GetFields();
foreach(var pair in dictionary)
{
var targetField = fields.FirstOrDefault(field => field.Name == pair.Key);
if(targetField != default)
{
if(targetField.FieldType == typeof(Int32))
{
targetField.SetValue(obj, Convert.ToInt32(pair.Value));
}
else if(targetField.FieldType == typeof(float))
{
// 以下、必要な型変換の処理を行う。
}
}
}
return obj;
}
}
Sample.cs
実際の利用方法を記述したサンプル。
using System.Collections.Generic;
using System.Linq;
using Firebase.Firestore;
[FirestoreData]
public class Sample
{
/// <summary>
/// The entities for Firestore.
/// </summary>
[FirestoreProperty]
public List<Dictionary<string, object>> entities { get; set; }
/// <summary>
/// The entities.
/// </summary>
public List<Entity> Entities
{
get
{
return entities.Select(entity => entity.ConvertClassFields<Entity>()).ToList();
}
set
{
entities = value.Select(entity => entity.GetFieldsAsDictonary()).ToList();
}
}
}