private void ReadAttributes() { // todo: use Expression API to generate getters/setters instead of reflection // [low priority due to low likelyness of 1M+ invocations] // todo: add [CanPersist] attribute and use it for canReadFunc //set key if [TrackingKey] detected PropertyInfo keyProperty = TargetType.GetProperties().SingleOrDefault(pi => pi.IsDefined(typeof(TrackingIdAttribute), true)); if (keyProperty != null) { idFunc = (t) => keyProperty.GetValue(t, null).ToString(); } //add properties that have [Trackable] applied foreach (PropertyInfo pi in TargetType.GetProperties()) { TrackableAttribute propTrackableAtt = pi.GetCustomAttributes(true).OfType <TrackableAttribute>().SingleOrDefault(); if (propTrackableAtt != null) { //use [DefaultValue] if present DefaultValueAttribute defaultAtt = pi.CustomAttributes.OfType <DefaultValueAttribute>().SingleOrDefault(); if (defaultAtt != null) { TrackedProperties[pi.Name] = new TrackedPropertyInfo(x => pi.GetValue(x), (x, v) => pi.SetValue(x, v), defaultAtt.Value); } else { TrackedProperties[pi.Name] = new TrackedPropertyInfo(x => pi.GetValue(x), (x, v) => pi.SetValue(x, v)); } } } foreach (EventInfo eventInfo in TargetType.GetEvents()) { var attributes = eventInfo.GetCustomAttributes(true); if (attributes.OfType <PersistOnAttribute>().Any()) { PersistOn(eventInfo.Name); } if (attributes.OfType <StopTrackingOnAttribute>().Any()) { StopTrackingOn(eventInfo.Name); } } }