Help making method generic - retrieving data from xml spreadsheet

I’m using QuickSheet to make ScriptableObjects from xml files and access the data in Unity

I need a generic method for extracting the data because I have multiple spreadsheets.

Each spreadsheet has three columns: ID, EN, ES.

The script takes the ID and language code, then grabs the relevant data.

The problem I have is that I don’t know how to get an enum in a generic way (not even sure that’s what I need to do?!).

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

[SerializeField] SerializedObjectSpreadshee serializedObjectSpreadshed;

public string GetData(int id, string languageCode)
{
    List<SerializedObjectSpreadshedData> items = new List<SerializedObjectSpreadshedData>();        // 1 Make a list

    items.AddRange(serializedObjectSpreadshed.dataArray);     // 2 Add the SO data

    AppleActionsData foundID = items.Find(x => x.ID[0] == id);        // 4 Search for the ID and add it to a list

    var foundAction = foundID.GetType().GetProperty(languageCode).GetValue(foundID, null);     // 5 Get the language data from the element

    var strings = ((IEnumerable)foundAction).Cast<object>()                           // 6 Convert language data to a string array
                              .Select(x => x == null ? x : x.ToString())
                              .ToArray();

    return strings[0].ToString();
}

This should help Enum.TryParse Method (System) | Microsoft Learn

1 Like

I’m going to first start with, you do a lot of unnecessary and expensive work in here. There’s no need to create a list, not a reason to ToArray the enumerable you got as ‘foundAction’, also foundAction is inherently an enumerable of object’s so no need to cast.

Also, how do you know that it’s going to be an IEnumerable? How do you even know that the passed in ‘languageCode’ is a valid property?

Anyways… this could be shortened up to:

public string GetData(int id, string languageCode)
{
    var foundId = serializedObjectSpreadshed.dataArray.FirstOrDefault(o => o.ID[0] == id); //you already have linq, use it
    if(foundID == null) return null; //id may not have been found

    var foundActions = foundID.GetType().GetProperty(languageCode).GetValue(foundID, null) as IEnumerable; //this should be refactored, there is probably a better way
    if(foundActions == null) return null; //languageCode may have been invalid

    return System.Convert.ToString(foundActions.FirstOrDefault()); //Convert.ToString handles nulls for you
}

To refactor this even cleaner, I’d have to see the implementation of SerializedObjectSpreadshedData.

As for enums. I’m not completely following how you expect this to work?

Do you want a ‘T GetData’ where the function returns the result not as a string, but instead converted to the T? How are you certain it is convertible? What are the types of ‘languageCode’ properties? Again, I’d like to see the imp for SerializedObjectSpreadshedData.