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.