Radost
Radost

Reputation: 131

Which is the best practice for extracting value from object?

Which is the best practice for extracting property from object ,so that we can take its value?

We have the following code structure:

public List<Group> Activities { get; set; } 

In Group we have:

public List<Span> Spans { get; set; }

In Span class we have:

public object Activity { get; set; }

In method I have the following loop that I want to take from object Activity property Id from TV:

foreach (var activity in result.Activities)
        {
            if (activity.Spans != null)
            {
                foreach (var span in activity.Spans)
                {
                    if (span.Activity != null)
                    {
                        foreach (var propertyInfo in typeof(Spans).GetProperties())
                        {
                            if (propertyInfo.Name == "Activity")
                            {
                             //take value from activity
                            }
                        }
                    }
                }
            }
        }

In span.Activity we have : { Time = 123, EndTime = 123, Points = [ -48, -49 ], PointsStart = [ 0, -2, ], TV = [ { "time": "123", "Id": 7, "TitleId": 5 } ] }

I need to take from TV the Id property value and add it later to a list. Which is the best practice to do it and how?

Upvotes: 1

Views: 137

Answers (2)

Zee
Zee

Reputation: 642

Since Activity inside span is an unknown and the object type is unknown, we'll have to use something like REGEX to match our values.

Here's something that works perfectly.

    var regexPatternToGetIdAndNumber = "\"([Id]+?)\"\\s*:\\s*\\d+";
    var regexPatternToGetNumber = "\\d+";

    foreach (var activity in activities.Where(a => a.Spans != null))
    {
        foreach (var span in activity.Spans)
        {
            foreach (var propertyInfo in span.GetType()
                                            .GetProperties()
                                            .Where(property => property.Name == "Activity"))//Get Properties of Span Names "Activity" 
            {
                var stringValue = propertyInfo.GetValue(span)?.ToString();
                if (string.IsNullOrEmpty(stringValue))
                {
                    continue; //If Value is empty, Skip it and continue
                }


                var idAndValueString = Regex.Match(stringValue, regexPatternToGetIdAndNumber).ToString(); //Returns "Id": 7

                var idValue = Regex.Match(idAndValueString, regexPatternToGetNumber).ToString(); //Returns 7;
            }
        }
    }

Let me know if it works for you :)

Upvotes: 2

Gabor
Gabor

Reputation: 3256

It may not be the best practise but you can use reflection.

You can use the EgonsoftHU.Extensions.Bcl nuget package that contains a GetPropertyValue() extension method that uses reflection:

using System.Linq;
using EgonsoftHU.Extensions.Bcl;

// Get all id values
var ids =
    result
        .Activities
        .SelectMany(activity => activity.Spans)
        .Where(spans => spans != null)
        .Select(span => span.Activity)
        .Where(activity => activity != null)
        .Select(
            activity =>
            {
                object tv = activity.GetPropertyValue("TV");

                object rawId = null;

                if (tv is IEnumerable e)
                {
                    rawId = e.Cast<object>().FirstOrDefault()?.GetPropertyValue("Id");
                }

                return rawId is int id ? (int?)id : (int?)null;
            }
        )
        .Where(id => id != null)
        .Cast<int>()
        .ToList();

Upvotes: 2

Related Questions