private static bool ShouldIgnoreMember(MemberInfo member, IReadOnlyInstanceTraversalContext context) { if (!member.HasAttribute(typeof(AuditAttribute))) { return(false); } var attr = member.GetCustomAttribute <AuditAttribute>(); return(!attr.Include); }
private string GetKey(IReadOnlyInstanceTraversalContext context, MemberInfo member) { var key = context.BreadcrumbAsString; if (string.IsNullOrWhiteSpace(key)) { return(member.Name); } if (context.Breadcrumb.Last().StartsWith($"{member.Name}[")) { return(key); } return($"{key}.{member.Name}"); }
/// <summary> /// Set change value /// </summary> /// <param name="member">The member representing the field/prop containing the value (i.e. might point to a list /// whereas the value is a member of that list)</param> /// <param name="value">The value of the field/property _OR_ an element in a list _OR_ a value in a dictionary</param> /// <param name="context">Context</param> private void SetValue(MemberInfo member, object value, IReadOnlyInstanceTraversalContext context) { // we are checking for the type of the // value directly on the value instead // through if (value != null && value.GetType().GetTypeInfo().IsClass&& !(value is string)) { // we do not want "changes" for objects, as the // coming changes for "object.field|property" are // much more interesting return; } var key = GetKey(context, member); if (!values.ContainsKey(key)) { values.Add( key, new StateChange { MemberInfo = member, Breadcrumb = key }); } switch (beingTraversed) { case BeingTraversed.Old: values[key].OldValue = value; break; case BeingTraversed.New: values[key].NewValue = value; break; case BeingTraversed.Nothing: default: throw new InvalidOperationException($"{nameof(beingTraversed)} must be set before you can {nameof(SetValue)}"); } }
public void OnMaxDepthReached(IReadOnlyInstanceTraversalContext context) { // by not blowing up, we make it possible // to continue working with the already // registered data, which can be useful }
public void OnMethod(MethodInfo method, IReadOnlyInstanceTraversalContext context) { // we do not care }
public void OnProperty(PropertyInfo property, Func <object> valueGetter, IReadOnlyInstanceTraversalContext context) { SetValue(property, valueGetter.Invoke(), context); }
public void OnField(FieldInfo field, Func <object> valueGetter, IReadOnlyInstanceTraversalContext context) { SetValue(field, valueGetter.Invoke(), context); }
public void OnConstructor(ConstructorInfo ctor, IReadOnlyInstanceTraversalContext context) { // we do not care }
public IInstanceListenerOnFieldOrPropResult OnProperty(PropertyInfo property, Func <object> valueGetter, IReadOnlyInstanceTraversalContext context) { if (propertyIgnoreFn.Invoke(property, context)) { return(new SimpleInstanceListenerOnFieldOrPropResult { DoContinueRecursion = false }); } SetValue(property, valueGetter.Invoke(), context); return(new SimpleInstanceListenerOnFieldOrPropResult { DoContinueRecursion = true }); }