I'm building a Firebase client that Synchronize Firebase tree with C# object. Firesharp is returning JSON data that represent the Firebase object, finally casting JSON into C# using NewtonSoft. I've done the casting and having a problem updating properties, here is C# object structure:
public class FirebaseObject
{
public string Path { get; set; }
public ServerTree Data { get; set; }
}
public class ServerTree
{
public Dictionary<string, Agent> Agents { get; set; }
public Dictionary<string, Report> Reports { get; set; }
public Dictionary<string, Store> Stores { get; set; }
public Dictionary<string, Dictionary<string, UserReport>> UserReports { get; set; } // <UserID, <ReportID, ReportData>>
public Dictionary<string, User> Users { get; set; }
public void ClearTree()
{
Agents = new Dictionary<string, Agent>();
Reports = new Dictionary<string, Report>();
Stores = new Dictionary<string, Store>();
UserReports = new Dictionary<string, Dictionary<string, UserReport>>();
Users = new Dictionary<string, User>();
}
}
public class Store
{
public string Id { get; set; }
public string Name { get; set; }
public int Order { get; set; }
}
public class Agent
{
public string Id { get; set; }
public string FingerPrint { get; set; }
public DateTime TimeStamp { get; set; }
}
public class User
{
public string Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public DateTime LastLogin { get; set; }
}
public class Report
{
public string Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string SqlQuery { get; set; }
public Parameters Parameters { get; set; }
public int Order { get; set; }
}
public class Parameters
{
public bool DateRange { get; set; }
public bool MultipleSource { get; set; }
public bool TimeRange { get; set; }
}
public class UserReport
{
public string UserId { get; set; }
public string ReportId { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public DateTime LastExecution { get; set; }
public Dictionary<string, Store> Stores { get; set; }
public bool Processed { get; set; }
}
When I update Firebase database tree Config.UserReport.Stores[].ID, Firesharp will fire an even giving the path of modified property and the value as following:
//userReports/ufHJ739MxccrJvXjxU4nfZArDY13/KKpgPGL2vDXSIo38dNd/stores/NYC-BDWY-121/id
What I want to achieve is to update the Id property dynamically using reflection, here is what I've done but it's not working. Where src is the C# object to synch and propName is the path received from Firesharp. The function should recursively go through the objects until it find the property Id and set its value. So far, it can go deep to first dictionary.
public static object GetDeepPropertyValue(object src, string propName)
{
if (propName.Contains('/'))
{
var Split = propName.Split(new string[] { "/" }, StringSplitOptions.RemoveEmptyEntries);
string RemainingProperty = propName.Substring(propName.IndexOf('/') + 1);
var property = src.GetType().GetProperties().FirstOrDefault(p => string.Equals(p.Name, Split[0], StringComparison.CurrentCultureIgnoreCase));
if (property != null) // Its a property
return GetDeepPropertyValue(property.GetValue(src, null), RemainingProperty);
else // Its a Dictionary Item
{
var prop = src.GetType().GetProperties().FirstOrDefault(p => string.Equals(p.Name, "Values", StringComparison.CurrentCultureIgnoreCase));
if (prop != null)
{
var mm = prop.GetValue(src, null);
return GetDeepPropertyValue(mm, RemainingProperty);
}
else
{
if (string.Equals(src.GetType().Name, "ValueCollection",
StringComparison.CurrentCultureIgnoreCase))
{
var collprop =
src.GetType().GetGenericArguments()[1].GetProperties()
.FirstOrDefault(
p => string.Equals(p.Name, "Values", StringComparison.CurrentCultureIgnoreCase));
var tm = collprop.GetValue(src, null);
if (collprop != null)
return GetDeepPropertyValue(tm, RemainingProperty);
else
return null;
}
else
{
return null;
}
}
}
}
else
{
var tt = src.GetType().GetProperties().FirstOrDefault(p => string.Equals(p.Name, propName, StringComparison.CurrentCultureIgnoreCase))?.GetValue(src, null);
return tt;
}
//GetProperty(propName).GetValue(src, null);
}
Thanks.
UPDATE
I think it would help to have the JSON data received from Firebase:
{
"config": {
"agents": {
"NYC-BDWY-121": {
"fingerprint": "375C-1E1E-D003-65D7-11D3-5A47-9165-FFZF",
"id": "NYC-BDWY-121",
"timestamp": "2016-6-21"
},
"NYC-BDWY-90": {
"fingerprint": "375C-1E1E-D003-65D7-11D3-5A47-9165-EE2F",
"id": "NYC-BDWY-90",
"timestamp": "2016-6-21"
}
},
"reports": {
"KKpgPGL2vDXSIo38dNd": {
"description": "Define report description here",
"id": "KKpgPGL2vDXSIo38dNd",
"name": "Sales Summary",
"order": 1,
"parameters": {
"dateRange": true,
"multipleSource": false,
"timeRange": false
},
"sqlQuery": "SELECT I.store_id..."
}
},
"stores": {
"NYC-BDWY-121": {
"key": "NYC-BDWY-121",
"name": "NYC Broadway 121st",
"order": 2
},
"NYC-BDWY-90": {
"key": "NYC-BDWY-90",
"name": "NYC Broadway 90th",
"order": 1
}
},
"userReports": {
"ufHJ739MxccrJvXjxU4nfZArDY13": {
"KKpgPGL2vDXSIo38dNd": {
"endDate": "2016-6-1",
"lastExecution": "2016-6-16",
"processed": false,
"startDate": "2016-5-1",
"stores": {
"NYC-BDWY-121": {
"id": "NYC-BDWY-121"
},
"NYC-BDWY-90": {
"id": "NYC-BDWY-90"
}
}
}
}
}
}
}