Skip to content

Commit 0a38690

Browse files
committed
🎨 refactor(Domain): 重构变更跟踪功能
- 将 IChangeTrackable 接口去泛型化,简化对象变更比较 - 优化 ChangeTrackingContext 类,增加类型检查 - 修改 DomainObjectBase 类,集成变更跟踪和描述功能 - 更新 IEntity 接口,使用泛型 IChangeTrackable - 调整测试项目引用,使用 framework.tests.props
1 parent 3e1848c commit 0a38690

File tree

10 files changed

+192
-137
lines changed

10 files changed

+192
-137
lines changed

Bing.All.sln

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "solution", "solution", "{B6
242242
common.props = common.props
243243
common.tests.props = common.tests.props
244244
framework.props = framework.props
245+
framework.tests.props = framework.tests.props
245246
LICENSE = LICENSE
246247
version.dev.props = version.dev.props
247248
version.props = version.props

framework.tests.props

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<Project>
2+
<PropertyGroup>
3+
<TargetFrameworks>net9.0;net8.0;net7.0;net6.0;net5.0;netcoreapp3.1;</TargetFrameworks>
4+
</PropertyGroup>
5+
6+
<Import Project="./common.tests.props"/>
7+
8+
</Project>

framework/src/Bing.Ddd.Domain/Bing/Domain/ChangeTracking/ChangeTrackingContext.cs

Lines changed: 33 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,7 @@ public ChangeTrackingContext(ChangedValueDescriptorCollection collection) =>
3838
/// <param name="description">描述</param>
3939
/// <param name="valueBeforeChange">变更前的值。范例:this.Name</param>
4040
/// <param name="valueAfterChange">变更后的值。范例:newEntity.Name</param>
41-
public void Add<TValue>(string propertyName, string description, TValue valueBeforeChange,
42-
TValue valueAfterChange)
41+
public void Add<TValue>(string propertyName, string description, TValue valueBeforeChange, TValue valueAfterChange)
4342
{
4443
if (Equals(valueBeforeChange, valueAfterChange))
4544
return;
@@ -53,34 +52,20 @@ public void Add<TValue>(string propertyName, string description, TValue valueBef
5352
/// <summary>
5453
/// 添加
5554
/// </summary>
56-
/// <typeparam name="TObject">领域对象类型</typeparam>
5755
/// <param name="leftObj">左对象</param>
5856
/// <param name="rightObj">右对象</param>
59-
public void Add<TObject>(IChangeTrackable<TObject> leftObj, TObject rightObj) where TObject : IDomainObject
57+
public void Add(IChangeTrackable leftObj, object rightObj)
6058
{
6159
if (Equals(leftObj, null))
6260
return;
6361
if (Equals(rightObj, null))
6462
return;
65-
_changedValueCollection.AddRange(leftObj.GetChanges(rightObj));
66-
}
63+
if (leftObj.GetType() != rightObj.GetType())
64+
throw new InvalidOperationException($"无法进行对象比较,类型不匹配: {leftObj.GetType().FullName}{rightObj.GetType().FullName}");
6765

68-
/// <summary>
69-
/// 添加
70-
/// </summary>
71-
/// <typeparam name="TObject">领域对象类型</typeparam>
72-
/// <typeparam name="TProperty">属性类型</typeparam>
73-
/// <typeparam name="TValue">值类型</typeparam>
74-
/// <param name="expression">属性表达式。范例:t => t.Name</param>
75-
/// <param name="obj">领域对象</param>
76-
/// <param name="newValue">新值。范例:newEntity.Name</param>
77-
public void Add<TObject, TProperty, TValue>(Expression<Func<TObject, TProperty>> expression, TObject obj, TValue newValue) where TObject : IDomainObject
78-
{
79-
var member = Lambdas.GetMemberExpression(expression);
80-
var name = Lambdas.GetMemberName(member);
81-
var desc = Reflection.Reflections.GetDisplayNameOrDescription(member.Member);
82-
var value = member.Member.GetPropertyValue(obj);
83-
Add(name, desc, Conv.To<TValue>(value), newValue);
66+
// 执行变更比较,并将变更结果添加到集合中
67+
var changes = leftObj.GetChanges(rightObj);
68+
_changedValueCollection.AddRange(changes);
8469
}
8570

8671
/// <summary>
@@ -89,23 +74,44 @@ public void Add<TObject, TProperty, TValue>(Expression<Func<TObject, TProperty>>
8974
/// <typeparam name="TObject">领域对象类型</typeparam>
9075
/// <param name="leftObjs">左对象列表</param>
9176
/// <param name="rightObjs">右对象列表</param>
92-
public void Add<TObject>(IEnumerable<IChangeTrackable<TObject>> leftObjs, IEnumerable<TObject> rightObjs)
77+
public void Add<TObject>(IEnumerable<IChangeTrackable> leftObjs, IEnumerable<TObject> rightObjs)
9378
where TObject : IDomainObject
9479
{
9580
if (Equals(leftObjs, null))
9681
return;
9782
if (Equals(rightObjs, null))
9883
return;
84+
85+
// 转换为列表,避免重复遍历
9986
var leftObjList = leftObjs.ToList();
10087
var rightObjList = rightObjs.ToList();
10188

102-
var length = leftObjList.Capacity > rightObjList.Count
103-
? rightObjList.Count
104-
: leftObjList.Count;
89+
// 确保列表长度一致
90+
var length = Math.Min(leftObjList.Count, rightObjList.Count);
91+
10592
for (var i = 0; i < length; i++)
10693
Add(leftObjList[i], rightObjList[i]);
10794
}
10895

96+
/// <summary>
97+
/// 添加
98+
/// </summary>
99+
/// <typeparam name="TObject">领域对象类型</typeparam>
100+
/// <typeparam name="TProperty">属性类型</typeparam>
101+
/// <typeparam name="TValue">值类型</typeparam>
102+
/// <param name="expression">属性表达式。范例:t => t.Name</param>
103+
/// <param name="obj">领域对象</param>
104+
/// <param name="newValue">新值。范例:newEntity.Name</param>
105+
public void Add<TObject, TProperty, TValue>(Expression<Func<TObject, TProperty>> expression, TObject obj, TValue newValue)
106+
where TObject : IDomainObject
107+
{
108+
var member = Lambdas.GetMemberExpression(expression);
109+
var name = Lambdas.GetMemberName(member);
110+
var desc = Reflection.Reflections.GetDisplayNameOrDescription(member.Member);
111+
var value = member.Member.GetPropertyValue(obj);
112+
Add(name, desc, Conv.To<TValue>(value), newValue);
113+
}
114+
109115
/// <summary>
110116
/// 填充
111117
/// </summary>
@@ -131,4 +137,4 @@ public void Add<TObject>(IEnumerable<IChangeTrackable<TObject>> leftObjs, IEnume
131137
/// 输出字符串
132138
/// </summary>
133139
public override string ToString() => Output();
134-
}
140+
}

framework/src/Bing.Ddd.Domain/Bing/Domain/ChangeTracking/ChangedValueDescriptor.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
namespace Bing.Domain.ChangeTracking;
22

33
/// <summary>
4-
/// 变更值
4+
/// 变更值描述符
55
/// </summary>
6-
public class ChangedValueDescriptor
6+
public record ChangedValueDescriptor
77
{
88
/// <summary>
99
/// 初始化一个<see cref="ChangedValueDescriptor"/>类型的实例
@@ -44,4 +44,4 @@ public ChangedValueDescriptor(string propertyName, string description, string ol
4444
/// 输出变更信息
4545
/// </summary>
4646
public override string ToString() => $"{PropertyName}({Description}),旧值:{OldValue},新值:{NewValue}";
47-
}
47+
}

framework/src/Bing.Ddd.Domain/Bing/Domain/ChangeTracking/ChangedValueDescriptorCollection.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,10 +101,10 @@ public void Populate(IEnumerable<ChangedValueDescriptor> descriptors)
101101
{
102102
if (descriptors == null || !descriptors.Any())
103103
return;
104-
var filtedDiscriptors = descriptors.Where(x => !_changedNameList.Contains(x.PropertyName)).ToList();
105-
if (!filtedDiscriptors.Any())
104+
var filteredDescriptors = descriptors.Where(x => !_changedNameList.Contains(x.PropertyName)).ToList();
105+
if (!filteredDescriptors.Any())
106106
return;
107-
foreach (var item in filtedDiscriptors)
107+
foreach (var item in filteredDescriptors)
108108
Add(item);
109109
}
110110

@@ -129,4 +129,4 @@ public override string ToString()
129129
result.AppendLine(item.ToString());
130130
return result.ToString();
131131
}
132-
}
132+
}
Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,23 @@
1-
using Bing.Domain.Entities;
2-
3-
namespace Bing.Domain.ChangeTracking;
1+
namespace Bing.Domain.ChangeTracking;
42

53
/// <summary>
6-
/// 变更跟踪
4+
/// 定义变更跟踪接口,用于检测对象属性的变更情况。
75
/// </summary>
8-
/// <typeparam name="TObject">领域对象类型</typeparam>
9-
public interface IChangeTrackable<in TObject> where TObject : IDomainObject
6+
/// <remarks>
7+
/// 该接口主要用于对比两个对象的状态差异,并返回变更详情。<br/>
8+
/// 适用于持久化对象(Entity)、领域对象(DomainObjectBase)等需要变更追踪的场景。
9+
/// </remarks>
10+
public interface IChangeTrackable
1011
{
1112
/// <summary>
12-
/// 获取变更值集合
13+
/// 获取对象的变更信息。
1314
/// </summary>
14-
/// <param name="otherObject">其它对象</param>
15-
ChangedValueDescriptorCollection GetChanges(TObject otherObject);
15+
/// <param name="otherObject">要比较的对象。</param>
16+
/// <returns>
17+
/// 返回 <see cref="ChangedValueDescriptorCollection"/>,其中包含当前对象与 <paramref name="otherObject"/> 之间的所有属性变更信息。
18+
/// </returns>
19+
/// <exception cref="InvalidOperationException">
20+
/// 当 <paramref name="otherObject"/> 的类型与当前对象类型不匹配时,会抛出该异常。
21+
/// </exception>
22+
ChangedValueDescriptorCollection GetChanges(object otherObject);
1623
}

0 commit comments

Comments
 (0)