1
\$\begingroup\$

I've the following scenario, I've got some viewmodel that need to persist their state on disk.

I've defined a custom attribute as:

[AttributeUsage(AttributeTargets.Property)]
public class FilterPesistableAttribute : Attribute
{
    public string NestedProperty { get; set; }
}

This attribute is put on the properties as you can see in the following Nunit test (you can copy and try it if you want):

  public class SavingFilterAttributeTests
  {
    [Test]
    public void TestSaveState()
    {
        var dummy = new Dummy();

        dummy.ID = 4;
        dummy.Nested = new Nested
        {NestedPropery = "Test", Inner = new Inner() {ID = 69}};
        Stopwatch sw = Stopwatch.StartNew();

        var result =  ViewModelStatePersistenceHelper.SaveState(dummy);

        sw.Stop();

        Console.WriteLine(sw.Elapsed);
    }

}

public class Dummy
{
    [FilterPesistable]
    public  int ID { get; set; }
    [FilterPesistable(NestedProperty = "Inner.ID")]
    public Nested Nested { get; set; }

    public Dummy()
    {
        Nested = new Nested();
    }
}

public class Nested
{
    public string NestedPropery
    {
        get; set;
    }

    public Inner Inner { get; set; }

    public Nested()
    {
        Inner = new Inner();
    }
}

public class Inner
{
    public  int ID { get; set; }
}

The method I need help on is the following:

  public static Dictionary<string, object> SaveState(object viewmodel)
    {
        if (viewmodel == null) return null;
        var res = new Dictionary<string, object>();

        var attributes = viewmodel.GetType().GetProperties().Where(prop => Attribute.IsDefined(prop, typeof(FilterPesistableAttribute)));

        var propertyInfos = attributes as IList<PropertyInfo> ?? attributes.ToList();

        if (propertyInfos.Any())
        {
            propertyInfos.ForEach(x =>
            {
                var value = x.GetValue(viewmodel, null);

                if (value == null) return;
                if (value.GetType().IsPrimitive)
                {
                    res.Add(x.Name, value);
                }
                else
                {
                    var attributes2 =
                        x.GetCustomAttributes(typeof(FilterPesistableAttribute), true) as
                            IList<FilterPesistableAttribute>;

                    var attribute = attributes2.FirstOrDefault();

                    if (attribute == null) return;
                    var a = GetPropertyValue(value, attribute.NestedProperty);
                    res.Add(attribute.NestedProperty, a);
                }
            });
        }
        return res;
    }

 public static class IEnumerableExtensions
{
    public static void ForEach<T>(this IEnumerable<T> collection, Action<T> action)
    {
        foreach (T item in collection)
        {
            action(item);
        }
    }
}

I wish to make this more performant and elegant.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.