diff --git a/Volo.Abp.sln b/Volo.Abp.sln index ce61195bed..8f561b22f5 100644 --- a/Volo.Abp.sln +++ b/Volo.Abp.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.26228.9 +VisualStudioVersion = 15.0.26430.6 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}" EndProject @@ -106,13 +106,15 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Identity.Web", "sr EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Identity.HttpApi.Client", "src\Volo.Abp.Identity.HttpApi.Client\Volo.Abp.Identity.HttpApi.Client.csproj", "{00B240B6-EC44-461A-9578-EF4F1BE9C688}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Autofac", "src\Volo.Abp.Autofac\Volo.Abp.Autofac.csproj", "{CECE1288-B5A1-4A6B-BEE0-331861F94983}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Autofac", "src\Volo.Abp.Autofac\Volo.Abp.Autofac.csproj", "{CECE1288-B5A1-4A6B-BEE0-331861F94983}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Castle.Core", "src\Volo.Abp.Castle.Core\Volo.Abp.Castle.Core.csproj", "{053F7446-0545-482E-9F29-9C96B926966C}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Castle.Core", "src\Volo.Abp.Castle.Core\Volo.Abp.Castle.Core.csproj", "{053F7446-0545-482E-9F29-9C96B926966C}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Autofac.Tests", "test\Volo.Abp.Autofac.Tests\Volo.Abp.Autofac.Tests.csproj", "{D8BE64D2-BD83-40F5-9783-D7FDDF668C45}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Autofac.Tests", "test\Volo.Abp.Autofac.Tests\Volo.Abp.Autofac.Tests.csproj", "{D8BE64D2-BD83-40F5-9783-D7FDDF668C45}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Castle.Core.Tests", "test\Volo.Abp.Castle.Core.Tests\Volo.Abp.Castle.Core.Tests.csproj", "{CE12E5C2-7B3E-4637-B6A3-274BB5C3DE16}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Castle.Core.Tests", "test\Volo.Abp.Castle.Core.Tests\Volo.Abp.Castle.Core.Tests.csproj", "{CE12E5C2-7B3E-4637-B6A3-274BB5C3DE16}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.AutoMapper", "src\Volo.Abp.AutoMapper\Volo.Abp.AutoMapper.csproj", "{D2F3594F-E2B9-4338-A022-F00C4E9A14C3}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -276,6 +278,10 @@ Global {CE12E5C2-7B3E-4637-B6A3-274BB5C3DE16}.Debug|Any CPU.Build.0 = Debug|Any CPU {CE12E5C2-7B3E-4637-B6A3-274BB5C3DE16}.Release|Any CPU.ActiveCfg = Release|Any CPU {CE12E5C2-7B3E-4637-B6A3-274BB5C3DE16}.Release|Any CPU.Build.0 = Release|Any CPU + {D2F3594F-E2B9-4338-A022-F00C4E9A14C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D2F3594F-E2B9-4338-A022-F00C4E9A14C3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D2F3594F-E2B9-4338-A022-F00C4E9A14C3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D2F3594F-E2B9-4338-A022-F00C4E9A14C3}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -329,5 +335,6 @@ Global {053F7446-0545-482E-9F29-9C96B926966C} = {4C753F64-0C93-4D65-96C2-A40893AFC1E8} {D8BE64D2-BD83-40F5-9783-D7FDDF668C45} = {37087D1B-3693-4E96-983D-A69F210BDE53} {CE12E5C2-7B3E-4637-B6A3-274BB5C3DE16} = {37087D1B-3693-4E96-983D-A69F210BDE53} + {D2F3594F-E2B9-4338-A022-F00C4E9A14C3} = {4C753F64-0C93-4D65-96C2-A40893AFC1E8} EndGlobalSection EndGlobal diff --git a/src/Volo.Abp.AutoMapper/Volo.Abp.AutoMapper.csproj b/src/Volo.Abp.AutoMapper/Volo.Abp.AutoMapper.csproj new file mode 100644 index 0000000000..6678671ddc --- /dev/null +++ b/src/Volo.Abp.AutoMapper/Volo.Abp.AutoMapper.csproj @@ -0,0 +1,23 @@ + + + + netstandard1.6 + Volo.Abp.AutoMapper + Volo.Abp.AutoMapper + 1.6.1 + $(PackageTargetFallback);dnxcore50 + false + false + false + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperConfiguration.cs b/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperConfiguration.cs new file mode 100644 index 0000000000..2665e5c950 --- /dev/null +++ b/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperConfiguration.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using AutoMapper; + +namespace Volo.Abp.AutoMapper +{ + public class AbpAutoMapperConfiguration : IAbpAutoMapperConfiguration + { + public List> Configurators { get; } + + public bool UseStaticMapper { get; set; } + + public AbpAutoMapperConfiguration() + { + UseStaticMapper = true; + Configurators = new List>(); + } + } +} \ No newline at end of file diff --git a/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperModule.cs b/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperModule.cs new file mode 100644 index 0000000000..c8eb26fc57 --- /dev/null +++ b/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperModule.cs @@ -0,0 +1,98 @@ +using System; +using AutoMapper; +using Microsoft.Extensions.Logging; +using Volo.Abp.Modularity; + +namespace Volo.Abp.AutoMapper +{ + public class AbpAutoMapperModule : AbpModule + { + //private readonly ITypeFinder _typeFinder; + + //private static volatile bool _createdMappingsBefore; + //private static readonly object SyncObj = new object(); + + //public AbpAutoMapperModule(ITypeFinder typeFinder) + //{ + // _typeFinder = typeFinder; + //} + + //public override void PreInitialize() + //{ + // IocManager.Register(); + + // Configuration.ReplaceService(); + + // Configuration.Modules.AbpAutoMapper().Configurators.Add(CreateCoreMappings); + //} + + //public override void PostInitialize() + //{ + // CreateMappings(); + //} + + //private void CreateMappings() + //{ + // lock (SyncObj) + // { + // Action configurer = configuration => + // { + // FindAndAutoMapTypes(configuration); + // foreach (var configurator in Configuration.Modules.AbpAutoMapper().Configurators) + // { + // configurator(configuration); + // } + // }; + + // if (Configuration.Modules.AbpAutoMapper().UseStaticMapper) + // { + // //We should prevent duplicate mapping in an application, since Mapper is static. + // if (!_createdMappingsBefore) + // { + // Mapper.Initialize(configurer); + // _createdMappingsBefore = true; + // } + + // IocManager.IocContainer.Register( + // Component.For().Instance(Mapper.Instance).LifestyleSingleton() + // ); + // } + // else + // { + // var config = new MapperConfiguration(configurer); + // IocManager.IocContainer.Register( + // Component.For().Instance(config.CreateMapper()).LifestyleSingleton() + // ); + // } + // } + //} + + //private void FindAndAutoMapTypes(IMapperConfigurationExpression configuration) + //{ + // var types = _typeFinder.Find(type => + // { + // var typeInfo = type.GetTypeInfo(); + // return typeInfo.IsDefined(typeof(AutoMapAttribute)) || + // typeInfo.IsDefined(typeof(AutoMapFromAttribute)) || + // typeInfo.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); + // } + //} + + //private void CreateCoreMappings(IMapperConfigurationExpression configuration) + //{ + // var localizationContext = IocManager.Resolve(); + + // configuration.CreateMap().ConvertUsing(ls => ls?.Localize(localizationContext)); + // configuration.CreateMap().ConvertUsing(ls => ls == null ? null : localizationContext.LocalizationManager.GetString(ls)); + //} + } +} diff --git a/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AutoMapAttribute.cs b/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AutoMapAttribute.cs new file mode 100644 index 0000000000..f5284776fc --- /dev/null +++ b/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AutoMapAttribute.cs @@ -0,0 +1,29 @@ +using System; +using AutoMapper; +using Volo.ExtensionMethods.Collections.Generic; + +namespace Volo.Abp.AutoMapper +{ + public class AutoMapAttribute : AutoMapAttributeBase + { + public AutoMapAttribute(params Type[] targetTypes) + : base(targetTypes) + { + + } + + public override void CreateMap(IMapperConfigurationExpression configuration, Type type) + { + if (TargetTypes.IsNullOrEmpty()) + { + return; + } + + foreach (var targetType in TargetTypes) + { + configuration.CreateMap(type, targetType, MemberList.Source); + configuration.CreateMap(targetType, type, MemberList.Destination); + } + } + } +} \ No newline at end of file diff --git a/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AutoMapAttributeBase.cs b/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AutoMapAttributeBase.cs new file mode 100644 index 0000000000..5756347380 --- /dev/null +++ b/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AutoMapAttributeBase.cs @@ -0,0 +1,17 @@ +using System; +using AutoMapper; + +namespace Volo.Abp.AutoMapper +{ + public abstract class AutoMapAttributeBase : Attribute + { + public Type[] TargetTypes { get; } + + protected AutoMapAttributeBase(params Type[] targetTypes) + { + TargetTypes = targetTypes; + } + + public abstract void CreateMap(IMapperConfigurationExpression configuration, Type type); + } +} \ No newline at end of file diff --git a/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AutoMapExtensions.cs b/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AutoMapExtensions.cs new file mode 100644 index 0000000000..32c0ad93fa --- /dev/null +++ b/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AutoMapExtensions.cs @@ -0,0 +1,32 @@ +using AutoMapper; + +namespace Volo.Abp.AutoMapper +{ + public static class AutoMapExtensions + { + /// + /// Converts an object to another using AutoMapper library. Creates a new object of . + /// There must be a mapping between objects before calling this method. + /// + /// Type of the destination object + /// Source object + public static TDestination MapTo(this object source) + { + return Mapper.Map(source); + } + + /// + /// Execute a mapping from the source object to the existing destination object + /// There must be a mapping between objects before calling this method. + /// + /// Source type + /// Destination type + /// Source object + /// Destination object + /// + public static TDestination MapTo(this TSource source, TDestination destination) + { + return Mapper.Map(source, destination); + } + } +} diff --git a/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AutoMapFromAttribute.cs b/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AutoMapFromAttribute.cs new file mode 100644 index 0000000000..9d0c765559 --- /dev/null +++ b/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AutoMapFromAttribute.cs @@ -0,0 +1,36 @@ +using System; +using AutoMapper; +using Volo.ExtensionMethods.Collections.Generic; + +namespace Volo.Abp.AutoMapper +{ + 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.CreateMap(targetType, type, MemberList); + } + } + } +} \ No newline at end of file diff --git a/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AutoMapToAttribute.cs b/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AutoMapToAttribute.cs new file mode 100644 index 0000000000..a0f3e4e26f --- /dev/null +++ b/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AutoMapToAttribute.cs @@ -0,0 +1,36 @@ +using System; +using AutoMapper; +using Volo.ExtensionMethods.Collections.Generic; + +namespace Volo.Abp.AutoMapper +{ + 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; + } + + foreach (var targetType in TargetTypes) + { + configuration.CreateMap(type, targetType, MemberList); + } + } + } +} \ No newline at end of file diff --git a/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AutoMapperConfigurationExtensions.cs b/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AutoMapperConfigurationExtensions.cs new file mode 100644 index 0000000000..579e5181d1 --- /dev/null +++ b/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AutoMapperConfigurationExtensions.cs @@ -0,0 +1,17 @@ +using System; +using System.Reflection; +using AutoMapper; + +namespace Volo.Abp.AutoMapper +{ + internal static class AutoMapperConfigurationExtensions + { + public static void CreateAutoAttributeMaps(this IMapperConfigurationExpression configuration, Type type) + { + foreach (var autoMapAttribute in type.GetTypeInfo().GetCustomAttributes()) + { + autoMapAttribute.CreateMap(configuration, type); + } + } + } +} \ No newline at end of file diff --git a/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AutoMapperObjectMapper.cs b/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AutoMapperObjectMapper.cs new file mode 100644 index 0000000000..dbb41da797 --- /dev/null +++ b/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AutoMapperObjectMapper.cs @@ -0,0 +1,24 @@ +using AutoMapper; + +namespace Volo.Abp.AutoMapper +{ + public class AutoMapperObjectMapper : Volo.Abp.ObjectMapping.IObjectMapper + { + private readonly IMapper _mapper; + + public AutoMapperObjectMapper(IMapper mapper) + { + _mapper = mapper; + } + + public TDestination Map(object source) + { + return _mapper.Map(source); + } + + public TDestination Map(TSource source, TDestination destination) + { + return _mapper.Map(source, destination); + } + } +} diff --git a/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/IAbpAutoMapperConfiguration.cs b/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/IAbpAutoMapperConfiguration.cs new file mode 100644 index 0000000000..f5e660a09f --- /dev/null +++ b/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/IAbpAutoMapperConfiguration.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using AutoMapper; + +namespace Volo.Abp.AutoMapper +{ + public interface IAbpAutoMapperConfiguration + { + List> Configurators { get; } + + /// + /// Use static . + /// Default: true. + /// + bool UseStaticMapper { get; set; } + } +} \ No newline at end of file diff --git a/src/Volo.Abp/Volo/Abp/ObjectMapping/IObjectMapper.cs b/src/Volo.Abp/Volo/Abp/ObjectMapping/IObjectMapper.cs new file mode 100644 index 0000000000..70212b1ff4 --- /dev/null +++ b/src/Volo.Abp/Volo/Abp/ObjectMapping/IObjectMapper.cs @@ -0,0 +1,25 @@ +namespace Volo.Abp.ObjectMapping +{ + /// + /// Defines a simple interface to map objects. + /// + public interface IObjectMapper + { + /// + /// Converts an object to another. Creates a new object of . + /// + /// Type of the destination object + /// Source object + TDestination Map(object source); + + /// + /// Execute a mapping from the source object to the existing destination object + /// + /// Source type + /// Destination type + /// Source object + /// Destination object + /// Returns the same object after mapping operation + TDestination Map(TSource source, TDestination destination); + } +} diff --git a/src/Volo.Abp/Volo/Abp/ObjectMapping/NotImplementedObjectMapper.cs b/src/Volo.Abp/Volo/Abp/ObjectMapping/NotImplementedObjectMapper.cs new file mode 100644 index 0000000000..064991e4d3 --- /dev/null +++ b/src/Volo.Abp/Volo/Abp/ObjectMapping/NotImplementedObjectMapper.cs @@ -0,0 +1,23 @@ +using System; +using Volo.DependencyInjection; + +namespace Volo.Abp.ObjectMapping +{ + public sealed class NotImplementedObjectMapper : IObjectMapper, ISingletonDependency + { + /// + /// Singleton instance. + /// + public static NotImplementedObjectMapper Instance { get; } = new NotImplementedObjectMapper(); + + public TDestination Map(object source) + { + throw new NotImplementedException("Abp.ObjectMapping.IObjectMapper should be implemented in order to map objects."); + } + + public TDestination Map(TSource source, TDestination destination) + { + throw new NotImplementedException("Abp.ObjectMapping.IObjectMapper should be implemented in order to map objects."); + } + } +} \ No newline at end of file