Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
N
netcoreplus
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
tsai
netcoreplus
Commits
b48125db
Commit
b48125db
authored
May 18, 2019
by
阿星Plus
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
AutoMapper 扩展
parent
10eb6466
Changes
15
Show whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
535 additions
and
1 deletion
+535
-1
AutoMapAttribute.cs
src/Plus.AutoMapper/AutoMapAttribute.cs
+32
-0
AutoMapAttributeBase.cs
src/Plus.AutoMapper/AutoMapAttributeBase.cs
+20
-0
AutoMapExtensions.cs
src/Plus.AutoMapper/AutoMapExtensions.cs
+35
-0
AutoMapFromAttribute.cs
src/Plus.AutoMapper/AutoMapFromAttribute.cs
+38
-0
AutoMapKeyAttribute.cs
src/Plus.AutoMapper/AutoMapKeyAttribute.cs
+12
-0
AutoMapToAttribute.cs
src/Plus.AutoMapper/AutoMapToAttribute.cs
+35
-0
AutoMapperConfigurationExtensions.cs
src/Plus.AutoMapper/AutoMapperConfigurationExtensions.cs
+124
-0
AutoMapperObjectMapper.cs
src/Plus.AutoMapper/AutoMapperObjectMapper.cs
+28
-0
IAutoMapRegistrar.cs
src/Plus.AutoMapper/IAutoMapRegistrar.cs
+12
-0
IPlusAutoMapperConfiguration.cs
src/Plus.AutoMapper/IPlusAutoMapperConfiguration.cs
+20
-0
Plus.AutoMapper.csproj
src/Plus.AutoMapper/Plus.AutoMapper.csproj
+10
-1
PlusAutoMapperConfiguration.cs
src/Plus.AutoMapper/PlusAutoMapperConfiguration.cs
+22
-0
PlusAutoMapperConfigurationExtensions.cs
src/Plus.AutoMapper/PlusAutoMapperConfigurationExtensions.cs
+15
-0
PlusAutoMapperModule.cs
src/Plus.AutoMapper/PlusAutoMapperModule.cs
+100
-0
PlusStartupConfigurationExtensions.cs
...nfiguration/Startup/PlusStartupConfigurationExtensions.cs
+32
-0
No files found.
src/Plus.AutoMapper/AutoMapAttribute.cs
0 → 100644
View file @
b48125db
using
AutoMapper
;
using
System
;
namespace
Plus.AutoMapper
{
/// <summary>
/// AutoMapAttribute
/// </summary>
public
class
AutoMapAttribute
:
AutoMapAttributeBase
{
public
AutoMapAttribute
(
params
Type
[]
targetTypes
)
:
base
(
targetTypes
)
{
}
public
override
void
CreateMap
(
IMapperConfigurationExpression
configuration
,
Type
type
)
{
if
(
TargetTypes
.
IsNullOrEmpty
())
{
return
;
}
configuration
.
CreateAutoAttributeMaps
(
type
,
TargetTypes
,
MemberList
.
Source
);
foreach
(
var
targetType
in
TargetTypes
)
{
configuration
.
CreateAutoAttributeMaps
(
targetType
,
new
[]
{
type
},
MemberList
.
Destination
);
}
}
}
}
\ No newline at end of file
src/Plus.AutoMapper/AutoMapAttributeBase.cs
0 → 100644
View file @
b48125db
using
AutoMapper
;
using
System
;
namespace
Plus.AutoMapper
{
/// <summary>
/// AutoMapAttributeBase
/// </summary>
public
abstract
class
AutoMapAttributeBase
:
Attribute
{
public
Type
[]
TargetTypes
{
get
;
private
set
;
}
protected
AutoMapAttributeBase
(
params
Type
[]
targetTypes
)
{
TargetTypes
=
targetTypes
;
}
public
abstract
void
CreateMap
(
IMapperConfigurationExpression
configuration
,
Type
type
);
}
}
\ No newline at end of file
src/Plus.AutoMapper/AutoMapExtensions.cs
0 → 100644
View file @
b48125db
using
AutoMapper
;
namespace
Plus.AutoMapper
{
/// <summary>
/// AutoMapExtensions
/// </summary>
public
static
class
AutoMapExtensions
{
/// <summary>
/// Converts an object to another using AutoMapper library. Creates a new object of <typeparamref name="TDestination"/>.
/// There must be a mapping between objects before calling this method.
/// </summary>
/// <typeparam name="TDestination">Type of the destination object</typeparam>
/// <param name="source">Source object</param>
public
static
TDestination
MapTo
<
TDestination
>(
this
object
source
)
{
return
Mapper
.
Map
<
TDestination
>(
source
);
}
/// <summary>
/// Execute a mapping from the source object to the existing destination object
/// There must be a mapping between objects before calling this method.
/// </summary>
/// <typeparam name="TSource">Source type</typeparam>
/// <typeparam name="TDestination">Destination type</typeparam>
/// <param name="source">Source object</param>
/// <param name="destination">Destination object</param>
/// <returns></returns>
public
static
TDestination
MapTo
<
TSource
,
TDestination
>(
this
TSource
source
,
TDestination
destination
)
{
return
Mapper
.
Map
(
source
,
destination
);
}
}
}
\ No newline at end of file
src/Plus.AutoMapper/AutoMapFromAttribute.cs
0 → 100644
View file @
b48125db
using
AutoMapper
;
using
System
;
namespace
Plus.AutoMapper
{
/// <summary>
/// AutoMapFromAttribute
/// </summary>
public
class
AutoMapFromAttribute
:
AutoMapAttributeBase
{
public
MemberList
MemberList
{
get
;
set
;
}
=
MemberList
.
Destination
;
public
AutoMapFromAttribute
(
params
Type
[]
targetTypes
)
:
base
(
targetTypes
)
{
}
public
AutoMapFromAttribute
(
MemberList
memberList
,
params
Type
[]
targetTypes
)
:
this
(
targetTypes
)
{
MemberList
=
memberList
;
}
public
override
void
CreateMap
(
IMapperConfigurationExpression
configuration
,
Type
type
)
{
if
(
TargetTypes
.
IsNullOrEmpty
())
{
return
;
}
foreach
(
var
targetType
in
TargetTypes
)
{
configuration
.
CreateAutoAttributeMaps
(
targetType
,
new
[]
{
type
},
MemberList
);
}
}
}
}
\ No newline at end of file
src/Plus.AutoMapper/AutoMapKeyAttribute.cs
0 → 100644
View file @
b48125db
using
System
;
namespace
Plus.AutoMapper
{
/// <summary>
/// AutoMapKeyAttribute
/// </summary>
public
class
AutoMapKeyAttribute
:
Attribute
{
}
}
\ No newline at end of file
src/Plus.AutoMapper/AutoMapToAttribute.cs
0 → 100644
View file @
b48125db
using
AutoMapper
;
using
System
;
namespace
Plus.AutoMapper
{
/// <summary>
/// AutoMapToAttribute
/// </summary>
public
class
AutoMapToAttribute
:
AutoMapAttributeBase
{
public
MemberList
MemberList
{
get
;
set
;
}
=
MemberList
.
Source
;
public
AutoMapToAttribute
(
params
Type
[]
targetTypes
)
:
base
(
targetTypes
)
{
}
public
AutoMapToAttribute
(
MemberList
memberList
,
params
Type
[]
targetTypes
)
:
this
(
targetTypes
)
{
MemberList
=
memberList
;
}
public
override
void
CreateMap
(
IMapperConfigurationExpression
configuration
,
Type
type
)
{
if
(
TargetTypes
.
IsNullOrEmpty
())
{
return
;
}
configuration
.
CreateAutoAttributeMaps
(
type
,
TargetTypes
,
MemberList
);
}
}
}
\ No newline at end of file
src/Plus.AutoMapper/AutoMapperConfigurationExtensions.cs
0 → 100644
View file @
b48125db
using
AutoMapper
;
using
System
;
using
System.Linq
;
using
System.Linq.Expressions
;
using
System.Reflection
;
namespace
Plus.AutoMapper
{
/// <summary>
/// AutoMapperConfigurationExtensions
/// </summary>
internal
static
class
AutoMapperConfigurationExtensions
{
private
static
readonly
object
SyncObj
=
new
object
();
public
static
void
CreateAutoAttributeMaps
(
this
IMapperConfigurationExpression
configuration
,
Type
type
)
{
lock
(
SyncObj
)
{
foreach
(
var
autoMapAttribute
in
type
.
GetTypeInfo
().
GetCustomAttributes
<
AutoMapAttributeBase
>())
{
autoMapAttribute
.
CreateMap
(
configuration
,
type
);
}
}
}
public
static
void
CreateAutoAttributeMaps
(
this
IMapperConfigurationExpression
configuration
,
Type
type
,
Type
[]
targetTypes
,
MemberList
memberList
)
{
//Get all the properties in the source that have the AutoMapKeyAttribute
var
sourceKeysPropertyInfo
=
type
.
GetProperties
()
.
Where
(
w
=>
w
.
GetCustomAttribute
<
AutoMapKeyAttribute
>()
!=
null
)
.
Select
(
s
=>
s
).
ToList
();
foreach
(
var
targetType
in
targetTypes
)
{
if
(!
sourceKeysPropertyInfo
.
Any
())
{
configuration
.
CreateMap
(
type
,
targetType
,
memberList
);
continue
;
}
BinaryExpression
equalityComparer
=
null
;
//In a lambda expression represent the source exemple : (source) => ...
ParameterExpression
sourceParameterExpression
=
Expression
.
Parameter
(
type
,
"source"
);
//In a lambda expression represent the target exemple : (target) => ...
ParameterExpression
targetParameterExpression
=
Expression
.
Parameter
(
targetType
,
"target"
);
//We could use multiple AutoMapKey to compare the determine equality
foreach
(
PropertyInfo
propertyInfo
in
sourceKeysPropertyInfo
)
{
//In a lambda expression represent a specfic property of a parameter exemple : (source) => source.Id
MemberExpression
sourcePropertyExpression
=
Expression
.
Property
(
sourceParameterExpression
,
propertyInfo
);
//Find the target a property with the same name to compare with
//Exemple if we have in source the attribut AutoMapKey on the Property Id we want to get Id in the target to compare agaisnt
var
targetPropertyInfo
=
targetType
.
GetProperty
(
sourcePropertyExpression
.
Member
.
Name
);
//It happen if the property with AutoMapKeyAttribute does not exist in target
if
(
targetPropertyInfo
is
null
)
{
continue
;
}
//In a lambda expression represent a specfic property of a parameter exemple : (target) => target.Id
MemberExpression
targetPropertyExpression
=
Expression
.
Property
(
targetParameterExpression
,
targetPropertyInfo
);
//Compare the property defined by AutoMapKey in the source agaisnt the same property in the target
//Exemple (source, target) => source.Id == target.Id
BinaryExpression
equal
=
Expression
.
Equal
(
sourcePropertyExpression
,
targetPropertyExpression
);
if
(
equalityComparer
is
null
)
{
equalityComparer
=
equal
;
}
else
{
//If we compare multiple key we want to make an and condition between
//Exemple : (source, target) => source.Email == target.Email && source.UserName == target.UserName
equalityComparer
=
Expression
.
And
(
equalityComparer
,
equal
);
}
}
//If there is not match for AutoMapKey in the target
//In this case we add the default mapping
if
(
equalityComparer
is
null
)
{
configuration
.
CreateMap
(
type
,
targetType
,
memberList
);
continue
;
}
//We need to make a generic type of Func<SourceType, TargetType, bool> to invoke later Expression.Lambda
var
funcGenericType
=
typeof
(
Func
<,,>).
MakeGenericType
(
type
,
targetType
,
typeof
(
bool
));
//Make a method info of Expression.Lambda<Func<SourceType, TargetType, bool>> to call later
var
lambdaMethodInfo
=
typeof
(
Expression
).
GetMethod
(
"Lambda"
,
2
,
1
).
MakeGenericMethod
(
funcGenericType
);
//Make the call to Expression.Lambda
var
expressionLambdaResult
=
lambdaMethodInfo
.
Invoke
(
null
,
new
object
[]
{
equalityComparer
,
new
ParameterExpression
[]
{
sourceParameterExpression
,
targetParameterExpression
}
});
//Get the method info of IMapperConfigurationExpression.CreateMap<Source, Target>
var
createMapMethodInfo
=
configuration
.
GetType
().
GetMethod
(
"CreateMap"
,
1
,
2
).
MakeGenericMethod
(
type
,
targetType
);
//Make the call to configuration.CreateMap<Source, Target>().
var
createMapResult
=
createMapMethodInfo
.
Invoke
(
configuration
,
new
object
[]
{
memberList
});
var
autoMapperCollectionAssembly
=
Assembly
.
Load
(
"AutoMapper.Collection"
);
var
autoMapperCollectionTypes
=
autoMapperCollectionAssembly
.
GetTypes
();
var
equalityComparisonGenericMethodInfo
=
autoMapperCollectionTypes
.
Where
(
w
=>
!
w
.
IsGenericType
&&
!
w
.
IsNested
)
.
SelectMany
(
s
=>
s
.
GetMethods
()).
Where
(
w
=>
w
.
Name
==
"EqualityComparison"
)
.
FirstOrDefault
()
.
MakeGenericMethod
(
type
,
targetType
);
//Make the call to EqualityComparison
//Exemple configuration.CreateMap<Source, Target>().EqualityComparison((source, target) => source.Id == target.Id)
equalityComparisonGenericMethodInfo
.
Invoke
(
createMapResult
,
new
object
[]
{
createMapResult
,
expressionLambdaResult
});
}
}
}
}
\ No newline at end of file
src/Plus.AutoMapper/AutoMapperObjectMapper.cs
0 → 100644
View file @
b48125db
using
AutoMapper
;
using
IObjectMapper
=
Plus
.
ObjectMapping
.
IObjectMapper
;
namespace
Plus.AutoMapper
{
/// <summary>
/// AutoMapperObjectMapper
/// </summary>
public
class
AutoMapperObjectMapper
:
IObjectMapper
{
private
readonly
IMapper
_mapper
;
public
AutoMapperObjectMapper
(
IMapper
mapper
)
{
_mapper
=
mapper
;
}
public
TDestination
Map
<
TDestination
>(
object
source
)
{
return
_mapper
.
Map
<
TDestination
>(
source
);
}
public
TDestination
Map
<
TSource
,
TDestination
>(
TSource
source
,
TDestination
destination
)
{
return
_mapper
.
Map
(
source
,
destination
);
}
}
}
\ No newline at end of file
src/Plus.AutoMapper/IAutoMapRegistrar.cs
0 → 100644
View file @
b48125db
using
AutoMapper
;
namespace
Plus.AutoMapper
{
/// <summary>
/// IAutoMapRegistrar
/// </summary>
public
interface
IAutoMapRegistrar
{
void
RegisterMaps
(
IMapperConfigurationExpression
config
);
}
}
\ No newline at end of file
src/Plus.AutoMapper/IPlusAutoMapperConfiguration.cs
0 → 100644
View file @
b48125db
using
AutoMapper
;
using
System
;
using
System.Collections.Generic
;
namespace
Plus.AutoMapper
{
/// <summary>
/// IPlusAutoMapperConfiguration
/// </summary>
public
interface
IPlusAutoMapperConfiguration
{
List
<
Action
<
IMapperConfigurationExpression
>>
Configurators
{
get
;
}
/// <summary>
/// Use static <see cref="Mapper.Instance"/>.
/// Default: true.
/// </summary>
bool
UseStaticMapper
{
get
;
set
;
}
}
}
\ No newline at end of file
src/Plus.AutoMapper/Plus.AutoMapper.csproj
View file @
b48125db
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AutoMapper" Version="8.1.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Plus.Extensions\Plus.Extensions.csproj" />
<ProjectReference Include="..\Plus\Plus.csproj" />
</ItemGroup>
</Project>
src/Plus.AutoMapper/PlusAutoMapperConfiguration.cs
0 → 100644
View file @
b48125db
using
AutoMapper
;
using
System
;
using
System.Collections.Generic
;
namespace
Plus.AutoMapper
{
/// <summary>
/// PlusAutoMapperConfiguration
/// </summary>
public
class
PlusAutoMapperConfiguration
:
IPlusAutoMapperConfiguration
{
public
List
<
Action
<
IMapperConfigurationExpression
>>
Configurators
{
get
;
}
public
bool
UseStaticMapper
{
get
;
set
;
}
public
PlusAutoMapperConfiguration
()
{
UseStaticMapper
=
true
;
Configurators
=
new
List
<
Action
<
IMapperConfigurationExpression
>>();
}
}
}
\ No newline at end of file
src/Plus.AutoMapper/PlusAutoMapperConfigurationExtensions.cs
0 → 100644
View file @
b48125db
using
Plus.Configuration.Startup
;
namespace
Plus.AutoMapper
{
/// <summary>
/// PlusAutoMapperConfigurationExtensions
/// </summary>
public
static
class
PlusAutoMapperConfigurationExtensions
{
public
static
IPlusAutoMapperConfiguration
PlusAutoMapper
(
this
IPlusStartupConfiguration
configuration
)
{
return
configuration
.
Get
<
IPlusAutoMapperConfiguration
>();
}
}
}
\ No newline at end of file
src/Plus.AutoMapper/PlusAutoMapperModule.cs
0 → 100644
View file @
b48125db
using
AutoMapper
;
using
Castle.MicroKernel.Registration
;
using
Plus.Configuration.Startup
;
using
Plus.Modules
;
using
Plus.Reflection
;
using
System
;
using
System.Reflection
;
using
IObjectMapper
=
Plus
.
ObjectMapping
.
IObjectMapper
;
namespace
Plus.AutoMapper
{
/// <summary>
/// PluseAutoMapperModule
/// </summary>
[
DependsOn
(
typeof
(
PlusLeadershipModule
))]
public
class
PluseAutoMapperModule
:
PlusModule
{
private
readonly
ITypeFinder
_typeFinder
;
private
static
volatile
bool
_createdMappingsBefore
;
private
static
readonly
object
SyncObj
=
new
object
();
public
PluseAutoMapperModule
(
ITypeFinder
typeFinder
)
{
_typeFinder
=
typeFinder
;
}
public
override
void
PreInitialize
()
{
IocManager
.
Register
<
IPlusAutoMapperConfiguration
,
PlusAutoMapperConfiguration
>();
Configuration
.
ReplaceService
<
IObjectMapper
,
AutoMapperObjectMapper
>();
}
public
override
void
PostInitialize
()
{
CreateMappings
();
}
private
void
CreateMappings
()
{
lock
(
SyncObj
)
{
Action
<
IMapperConfigurationExpression
>
configurer
=
configuration
=>
{
FindAndAutoMapTypes
(
configuration
);
foreach
(
var
configurator
in
Configuration
.
PlusAutoMapper
().
Configurators
)
{
configurator
(
configuration
);
}
};
if
(
Configuration
.
PlusAutoMapper
().
UseStaticMapper
)
{
// 防止重复映射
if
(!
_createdMappingsBefore
)
{
Mapper
.
Initialize
(
configurer
);
_createdMappingsBefore
=
true
;
}
IocManager
.
IocContainer
.
Register
(
Component
.
For
<
IConfigurationProvider
>().
Instance
(
Mapper
.
Configuration
).
LifestyleSingleton
()
);
IocManager
.
IocContainer
.
Register
(
Component
.
For
<
IMapper
>().
Instance
(
Mapper
.
Instance
).
LifestyleSingleton
()
);
}
else
{
var
config
=
new
MapperConfiguration
(
configurer
);
IocManager
.
IocContainer
.
Register
(
Component
.
For
<
IConfigurationProvider
>().
Instance
(
config
).
LifestyleSingleton
()
);
IocManager
.
IocContainer
.
Register
(
Component
.
For
<
IMapper
>().
Instance
(
config
.
CreateMapper
()).
LifestyleSingleton
()
);
}
}
}
private
void
FindAndAutoMapTypes
(
IMapperConfigurationExpression
configuration
)
{
var
types
=
_typeFinder
.
Find
(
type
=>
{
var
typeInfo
=
type
.
GetTypeInfo
();
return
type
.
IsDefined
(
typeof
(
AutoMapAttribute
))
||
type
.
IsDefined
(
typeof
(
AutoMapFromAttribute
))
||
type
.
IsDefined
(
typeof
(
AutoMapToAttribute
));
});
Logger
.
DebugFormat
(
"Found {0} classes define auto mapping attributes"
,
types
.
Length
);
foreach
(
var
type
in
types
)
{
Logger
.
Debug
(
type
.
FullName
);
configuration
.
CreateAutoAttributeMaps
(
type
);
}
}
}
}
\ No newline at end of file
src/Plus/Configuration/Startup/PlusStartupConfigurationExtensions.cs
0 → 100644
View file @
b48125db
using
Plus.Dependency
;
using
System
;
namespace
Plus.Configuration.Startup
{
/// <summary>
/// PlusStartupConfigurationExtensions
/// </summary>
public
static
class
PlusStartupConfigurationExtensions
{
public
static
void
ReplaceService
(
this
IPlusStartupConfiguration
configuration
,
Type
type
,
Type
impl
,
DependencyLifeStyle
lifeStyle
=
DependencyLifeStyle
.
Singleton
)
{
configuration
.
ReplaceService
(
type
,
delegate
{
configuration
.
IocManager
.
Register
(
type
,
impl
,
lifeStyle
);
});
}
public
static
void
ReplaceService
<
TType
,
TImpl
>(
this
IPlusStartupConfiguration
configuration
,
DependencyLifeStyle
lifeStyle
=
DependencyLifeStyle
.
Singleton
)
where
TType
:
class
where
TImpl
:
class
,
TType
{
configuration
.
ReplaceService
(
typeof
(
TType
),
delegate
{
configuration
.
IocManager
.
Register
<
TType
,
TImpl
>(
lifeStyle
);
});
}
public
static
void
ReplaceService
<
TType
>(
this
IPlusStartupConfiguration
configuration
,
Action
replaceAction
)
where
TType
:
class
{
configuration
.
ReplaceService
(
typeof
(
TType
),
replaceAction
);
}
}
}
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment