-
Notifications
You must be signed in to change notification settings - Fork 1
/
ChangeTracker.cs
75 lines (60 loc) · 2.77 KB
/
ChangeTracker.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
using AO.Models.Attributes;
using AO.Models.Enums;
using AO.Models.Static;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace Dapper.CX.Classes
{
public class ChangeTracker<TModel> : Dictionary<string, object>
{
private readonly Dictionary<string, PropertyInfo> _properties;
private readonly IEnumerable<string> _ignoreProps;
public TModel Instance { get; set; }
public ChangeTracker(TModel @object)
{
Instance = @object;
var props = SqlBuilder.GetMappedProperties(@object.GetType(), SaveAction.Update);
_ignoreProps = props.Where(pi => pi.HasAttribute<NoChangeTrackingAttribute>()).Select(pi => pi.Name);
_properties = props.ToDictionary(pi => pi.Name);
foreach (var pi in props) Add(pi.GetColumnName(), pi.GetValue(@object));
}
/// <summary>
/// call this after you've made desired changes to your model class instance to get the names of modified properties
/// </summary>
public string[] GetModifiedColumns(SaveAction? saveAction = null)
{
return GetModifiedProperties(saveAction)
.Select(kp => kp.Key)
.ToArray();
}
protected IEnumerable<KeyValuePair<string, PropertyInfo>> GetModifiedProperties(SaveAction? saveAction = null, bool loggableOnly = false)
{
Func<KeyValuePair<string, PropertyInfo>, bool> filter = (kp) => IsModified(kp, Instance);
if (saveAction.HasValue)
{
filter = (kp) => IsModified(kp, Instance) && kp.Value.AllowSaveAction(saveAction.Value);
}
return _properties.Where(kp => filter(kp) && isLogged(kp));
bool isLogged(KeyValuePair<string, PropertyInfo> kp)
{
// if not excluding ignore props, then include this property
if (!loggableOnly) return true;
// otherwise, don't log ignored properties
return !_ignoreProps.Contains(kp.Key);
}
}
private bool IsModified(KeyValuePair<string, PropertyInfo> kp, TModel @object)
{
// when using logged change tracker, there might be ignored properties that we need to manually exclude here
if (!ContainsKey(kp.Key)) return false;
var value = kp.Value.GetValue(@object);
return
(value == null ^ this[kp.Key] == null) ? true :
(value == null && this[kp.Key] == null) ? false :
!value.Equals(this[kp.Key]);
}
public bool HasChanges(SaveAction? saveAction = null, bool loggableOnly = false) => GetModifiedProperties(saveAction, loggableOnly).Any();
}
}