投影接口定义IProjection接口很简单只有TryConvert一个方法相同类型对象的转化,返回是否成功以及转化后的结果约定不符合规则就不转化一般情况下转化成功的结果会和源对象不同当然经过多次投影后也可能会和源对象相同了public interface IProjectionT { bool TryConvert(T source, out T result); }2. 三种投影方式2.1 使用前缀投影来演示前缀投影就是把成员前面加个前缀来映射sourceMembers模拟对User的反射通过Projection.Prefix(User)创建一个前缀投影如果没有User前缀,就增加User如果有User前缀就不处理public record User(int Id, string UserName); public record UserDTO(int UserId, string UserName); var sourceMembers new Dictionarystring, FuncUser, object() { [nameof(User.Id)] obj obj.Id, [nameof(User.UserName)] obj obj.UserName }; var projection Projection.Prefix(User);2.2 Filter投影的Case2.2.1 csharp代码IDictionarystring, FuncUser, object result projection.Filter(sourceMembers); Assert.Single(result); Assert.True(result.ContainsKey(nameof(UserDTO.UserId)));2.2.2 sql表示SELECT Id AS UserId FROM User2.2.3 影像表示UserFilterIdUserNameUserId2.3 Through投影的Case2.3.1 csharp代码IDictionarystring, FuncUser, object result projection.Through(sourceMembers); Assert.Equal(sourceMembers.Count, result.Count); Assert.True(result.ContainsKey(nameof(UserDTO.UserId))); Assert.True(result.ContainsKey(nameof(UserDTO.UserName)));2.3.2 sql表示SELECT Id AS UserId,UserName FROM User2.3.3 影像表示UserThroughThroughIdUserNameUserIdUserName2.4 Cross投影的CasePocoEmit.Mapper重构用的就是Cross投影2.4.1 csharp代码IDictionarystring, FuncUser, object result projection.Cross(sourceMembers); Assert.Equal(3, result.Count); Assert.True(result.ContainsKey(nameof(User.Id))); Assert.True(result.ContainsKey(nameof(UserDTO.UserId))); Assert.True(result.ContainsKey(nameof(UserDTO.UserName)));2.4.2 sql表示SELECT Id,UserName,Id AS UserId FROM User2.4.3 影像表示UserCrossCrossCrossIdUserNameIdUserNameUserId3. 投影支持横向扩展这里说的横向就是投影并联把多个投影组合成多分支的映射规则通过FirstReturn或ToFirstReturn方法实现3.1 横向扩展的Case// 包含User或U前缀就去掉前缀 var user Projection.RemovePrefix(User); var u Projection.RemovePrefix(U); var projection Projection.FirstReturn(user, u); [Theory] [InlineData(UserId, Id)] [InlineData(UId, Id)] [InlineData(UUserName, UserName)] [InlineData(UserUName, UName)] public void TryConvert(string source, string expected) { projection.TryConvert(source, out var result); Assert.Equal(expected, result); }3.2 影像表示横向扩展RemoveUser和RemoveU两个并联的投影并联投影按照顺序依次尝试直到有一个投影成功了就返回结果expectedsourceRemoveUserRemoveURemoveURemoveUserUserIdUIdUUserNameUserUNameIdUserNameUName二、投影在PocoEmit.Mapper中的应用1. AddPrefix1.1 AddPrefix的CaseIMapper mapper Mapper.Create(); mapper.ConfigureMapAutoUserDTO, User() .Source .AddPrefix(User); var source new AutoUserDTO { UserId 222, UserName Jxj2 }; var converter mapper.GetConverterAutoUserDTO, User(); var result converter.Convert(source); Assert.NotNull(result); Assert.Equal(source.UserId, result.Id.ToString()); Assert.Equal(source.UserName, result.UserName);1.2 AddPrefix使用的是去除前缀投影(RemovePrefix)AddPrefix(User)会调用Projection.RemovePrefix(User)来创建一个去除前缀投影AutoUserDTO两个成员分别是UserId和UserNameUser两个成员分别是Id和UserName对AutoUserDTO投影的效果相当于sql: SELECT UserId,UserName,UserId AS Id FROM AutoUserDTO通过这个投影,两边的成员名就能完美匹配上了1.3 影像演示一下这个过程UserAutoUserDTO投影AutoUserDTORemoveUserRemoveUserMappingMappingUserIdUserNameUserIdUserNameIdNameIdUserName1.4 使用前缀投影(Prefix)也可以实现类似的效果通过Projection.Prefix(User)创建一个前缀投影这时就需要对User进行投影对User投影的效果相当于sql: SELECT Id,UserName,Id AS UserId FROM User
投影投影接口定义
投影接口定义IProjection接口很简单只有TryConvert一个方法相同类型对象的转化,返回是否成功以及转化后的结果约定不符合规则就不转化一般情况下转化成功的结果会和源对象不同当然经过多次投影后也可能会和源对象相同了public interface IProjectionT { bool TryConvert(T source, out T result); }2. 三种投影方式2.1 使用前缀投影来演示前缀投影就是把成员前面加个前缀来映射sourceMembers模拟对User的反射通过Projection.Prefix(User)创建一个前缀投影如果没有User前缀,就增加User如果有User前缀就不处理public record User(int Id, string UserName); public record UserDTO(int UserId, string UserName); var sourceMembers new Dictionarystring, FuncUser, object() { [nameof(User.Id)] obj obj.Id, [nameof(User.UserName)] obj obj.UserName }; var projection Projection.Prefix(User);2.2 Filter投影的Case2.2.1 csharp代码IDictionarystring, FuncUser, object result projection.Filter(sourceMembers); Assert.Single(result); Assert.True(result.ContainsKey(nameof(UserDTO.UserId)));2.2.2 sql表示SELECT Id AS UserId FROM User2.2.3 影像表示UserFilterIdUserNameUserId2.3 Through投影的Case2.3.1 csharp代码IDictionarystring, FuncUser, object result projection.Through(sourceMembers); Assert.Equal(sourceMembers.Count, result.Count); Assert.True(result.ContainsKey(nameof(UserDTO.UserId))); Assert.True(result.ContainsKey(nameof(UserDTO.UserName)));2.3.2 sql表示SELECT Id AS UserId,UserName FROM User2.3.3 影像表示UserThroughThroughIdUserNameUserIdUserName2.4 Cross投影的CasePocoEmit.Mapper重构用的就是Cross投影2.4.1 csharp代码IDictionarystring, FuncUser, object result projection.Cross(sourceMembers); Assert.Equal(3, result.Count); Assert.True(result.ContainsKey(nameof(User.Id))); Assert.True(result.ContainsKey(nameof(UserDTO.UserId))); Assert.True(result.ContainsKey(nameof(UserDTO.UserName)));2.4.2 sql表示SELECT Id,UserName,Id AS UserId FROM User2.4.3 影像表示UserCrossCrossCrossIdUserNameIdUserNameUserId3. 投影支持横向扩展这里说的横向就是投影并联把多个投影组合成多分支的映射规则通过FirstReturn或ToFirstReturn方法实现3.1 横向扩展的Case// 包含User或U前缀就去掉前缀 var user Projection.RemovePrefix(User); var u Projection.RemovePrefix(U); var projection Projection.FirstReturn(user, u); [Theory] [InlineData(UserId, Id)] [InlineData(UId, Id)] [InlineData(UUserName, UserName)] [InlineData(UserUName, UName)] public void TryConvert(string source, string expected) { projection.TryConvert(source, out var result); Assert.Equal(expected, result); }3.2 影像表示横向扩展RemoveUser和RemoveU两个并联的投影并联投影按照顺序依次尝试直到有一个投影成功了就返回结果expectedsourceRemoveUserRemoveURemoveURemoveUserUserIdUIdUUserNameUserUNameIdUserNameUName二、投影在PocoEmit.Mapper中的应用1. AddPrefix1.1 AddPrefix的CaseIMapper mapper Mapper.Create(); mapper.ConfigureMapAutoUserDTO, User() .Source .AddPrefix(User); var source new AutoUserDTO { UserId 222, UserName Jxj2 }; var converter mapper.GetConverterAutoUserDTO, User(); var result converter.Convert(source); Assert.NotNull(result); Assert.Equal(source.UserId, result.Id.ToString()); Assert.Equal(source.UserName, result.UserName);1.2 AddPrefix使用的是去除前缀投影(RemovePrefix)AddPrefix(User)会调用Projection.RemovePrefix(User)来创建一个去除前缀投影AutoUserDTO两个成员分别是UserId和UserNameUser两个成员分别是Id和UserName对AutoUserDTO投影的效果相当于sql: SELECT UserId,UserName,UserId AS Id FROM AutoUserDTO通过这个投影,两边的成员名就能完美匹配上了1.3 影像演示一下这个过程UserAutoUserDTO投影AutoUserDTORemoveUserRemoveUserMappingMappingUserIdUserNameUserIdUserNameIdNameIdUserName1.4 使用前缀投影(Prefix)也可以实现类似的效果通过Projection.Prefix(User)创建一个前缀投影这时就需要对User进行投影对User投影的效果相当于sql: SELECT Id,UserName,Id AS UserId FROM User