diff --git a/Volo.Abp.sln b/Volo.Abp.sln index ba0cb91ba9..efe6c1f39e 100644 --- a/Volo.Abp.sln +++ b/Volo.Abp.sln @@ -274,11 +274,17 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Permissions.Applic EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Permissions.Application", "src\Volo.Abp.Permissions.Application\Volo.Abp.Permissions.Application.csproj", "{90197499-CBB6-4C8C-90E6-8718CD755C04}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Caching", "src\Volo.Abp.Caching\Volo.Abp.Caching.csproj", "{A5B650AB-A67F-4A4C-9F81-7B5471CA1331}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Caching", "src\Volo.Abp.Caching\Volo.Abp.Caching.csproj", "{A5B650AB-A67F-4A4C-9F81-7B5471CA1331}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.EventBus", "src\Volo.Abp.EventBus\Volo.Abp.EventBus.csproj", "{D9455AE7-2E0C-4647-9880-F5831BCEE3D8}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.EventBus", "src\Volo.Abp.EventBus\Volo.Abp.EventBus.csproj", "{D9455AE7-2E0C-4647-9880-F5831BCEE3D8}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.EventBus.Tests", "test\Volo.Abp.EventBus.Tests\Volo.Abp.EventBus.Tests.csproj", "{8C327AA0-BBED-4F8B-A88E-1DD97B04E58F}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.EventBus.Tests", "test\Volo.Abp.EventBus.Tests\Volo.Abp.EventBus.Tests.csproj", "{8C327AA0-BBED-4F8B-A88E-1DD97B04E58F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Caching.Tests", "test\Volo.Abp.Caching.Tests\Volo.Abp.Caching.Tests.csproj", "{B417D97C-330A-42CE-BDC6-93355B0A959A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Serialization", "src\Volo.Abp.Serialization\Volo.Abp.Serialization.csproj", "{38EF3EC8-9915-4216-B646-4BEE07006943}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Serialization.Tests", "test\Volo.Abp.Serialization.Tests\Volo.Abp.Serialization.Tests.csproj", "{65FB5893-7CB6-4694-A692-7E666E347D29}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -734,6 +740,18 @@ Global {8C327AA0-BBED-4F8B-A88E-1DD97B04E58F}.Debug|Any CPU.Build.0 = Debug|Any CPU {8C327AA0-BBED-4F8B-A88E-1DD97B04E58F}.Release|Any CPU.ActiveCfg = Release|Any CPU {8C327AA0-BBED-4F8B-A88E-1DD97B04E58F}.Release|Any CPU.Build.0 = Release|Any CPU + {B417D97C-330A-42CE-BDC6-93355B0A959A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B417D97C-330A-42CE-BDC6-93355B0A959A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B417D97C-330A-42CE-BDC6-93355B0A959A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B417D97C-330A-42CE-BDC6-93355B0A959A}.Release|Any CPU.Build.0 = Release|Any CPU + {38EF3EC8-9915-4216-B646-4BEE07006943}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {38EF3EC8-9915-4216-B646-4BEE07006943}.Debug|Any CPU.Build.0 = Debug|Any CPU + {38EF3EC8-9915-4216-B646-4BEE07006943}.Release|Any CPU.ActiveCfg = Release|Any CPU + {38EF3EC8-9915-4216-B646-4BEE07006943}.Release|Any CPU.Build.0 = Release|Any CPU + {65FB5893-7CB6-4694-A692-7E666E347D29}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {65FB5893-7CB6-4694-A692-7E666E347D29}.Debug|Any CPU.Build.0 = Debug|Any CPU + {65FB5893-7CB6-4694-A692-7E666E347D29}.Release|Any CPU.ActiveCfg = Release|Any CPU + {65FB5893-7CB6-4694-A692-7E666E347D29}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -870,6 +888,9 @@ Global {A5B650AB-A67F-4A4C-9F81-7B5471CA1331} = {4C753F64-0C93-4D65-96C2-A40893AFC1E8} {D9455AE7-2E0C-4647-9880-F5831BCEE3D8} = {4C753F64-0C93-4D65-96C2-A40893AFC1E8} {8C327AA0-BBED-4F8B-A88E-1DD97B04E58F} = {37087D1B-3693-4E96-983D-A69F210BDE53} + {B417D97C-330A-42CE-BDC6-93355B0A959A} = {37087D1B-3693-4E96-983D-A69F210BDE53} + {38EF3EC8-9915-4216-B646-4BEE07006943} = {4C753F64-0C93-4D65-96C2-A40893AFC1E8} + {65FB5893-7CB6-4694-A692-7E666E347D29} = {37087D1B-3693-4E96-983D-A69F210BDE53} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5} diff --git a/src/Volo.Abp.Caching/Volo.Abp.Caching.csproj b/src/Volo.Abp.Caching/Volo.Abp.Caching.csproj index f588132fd6..e8779ef390 100644 --- a/src/Volo.Abp.Caching/Volo.Abp.Caching.csproj +++ b/src/Volo.Abp.Caching/Volo.Abp.Caching.csproj @@ -19,6 +19,7 @@ + diff --git a/src/Volo.Abp.Caching/Volo.Abp.Caching.csproj.DotSettings b/src/Volo.Abp.Caching/Volo.Abp.Caching.csproj.DotSettings new file mode 100644 index 0000000000..58ad6c8854 --- /dev/null +++ b/src/Volo.Abp.Caching/Volo.Abp.Caching.csproj.DotSettings @@ -0,0 +1,2 @@ + + CSharp71 \ No newline at end of file diff --git a/src/Volo.Abp.Caching/Volo/Abp/Caching/AbpCachingModule.cs b/src/Volo.Abp.Caching/Volo/Abp/Caching/AbpCachingModule.cs index 114f093812..aca65dd1f3 100644 --- a/src/Volo.Abp.Caching/Volo/Abp/Caching/AbpCachingModule.cs +++ b/src/Volo.Abp.Caching/Volo/Abp/Caching/AbpCachingModule.cs @@ -1,8 +1,10 @@ using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Modularity; +using Volo.Abp.Threading; namespace Volo.Abp.Caching { + [DependsOn(typeof(AbpThreadingModule))] public class AbpCachingModule : AbpModule { public override void ConfigureServices(IServiceCollection services) @@ -11,6 +13,8 @@ namespace Volo.Abp.Caching services.AddDistributedMemoryCache(); services.AddAssemblyOf(); + + services.AddSingleton(typeof(IDistributedCache<>), typeof(DistributedCache<>)); } } } diff --git a/src/Volo.Abp.Caching/Volo/Abp/Caching/DistributedCache.cs b/src/Volo.Abp.Caching/Volo/Abp/Caching/DistributedCache.cs new file mode 100644 index 0000000000..78bfd77cf0 --- /dev/null +++ b/src/Volo.Abp.Caching/Volo/Abp/Caching/DistributedCache.cs @@ -0,0 +1,46 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Caching.Distributed; +using Volo.Abp.Threading; + +namespace Volo.Abp.Caching +{ + public class DistributedCache : IDistributedCache + where TCacheItem : class + { + protected IDistributedCache Cache { get; } + + public ICancellationTokenProvider CancellationTokenProvider { get; } + + public DistributedCache( + IDistributedCache cache, + ICancellationTokenProvider cancellationTokenProvider) + { + Cache = cache; + CancellationTokenProvider = cancellationTokenProvider; + } + + public async Task GetAsync(string key, CancellationToken token = default) + { + var cachedValue = await Cache.GetAsync(key, CancellationTokenProvider.FallbackToProvider(token)); + if (cachedValue == null) + { + return null; + } + + throw new NotImplementedException(); + } + + public Task SetAsync(string key, TCacheItem value, DistributedCacheEntryOptions options = null, + CancellationToken token = default) + { + throw new System.NotImplementedException(); + } + + public Task RemoveAsync(string key, CancellationToken token = default) + { + return Cache.RemoveAsync(key, CancellationTokenProvider.FallbackToProvider(token)); + } + } +} \ No newline at end of file diff --git a/src/Volo.Abp.Caching/Volo/Abp/Caching/IDistributedCache.cs b/src/Volo.Abp.Caching/Volo/Abp/Caching/IDistributedCache.cs new file mode 100644 index 0000000000..e6da33bf67 --- /dev/null +++ b/src/Volo.Abp.Caching/Volo/Abp/Caching/IDistributedCache.cs @@ -0,0 +1,28 @@ +using System.Threading; +using System.Threading.Tasks; +using JetBrains.Annotations; +using Microsoft.Extensions.Caching.Distributed; + +namespace Volo.Abp.Caching +{ + public interface IDistributedCache + where TCacheItem : class + { + Task GetAsync( + [NotNull] string key, + CancellationToken token = default + ); + + Task SetAsync( + [NotNull] string key, + [NotNull] TCacheItem value, + [CanBeNull] DistributedCacheEntryOptions options = null, + CancellationToken token = default + ); + + Task RemoveAsync( + string key, + CancellationToken token = default + ); + } +} diff --git a/src/Volo.Abp.Permissions.Domain/Volo/Abp/Permissions/PermissionStore.cs b/src/Volo.Abp.Permissions.Domain/Volo/Abp/Permissions/PermissionStore.cs index 2b84b3e8e5..ab8bc997cc 100644 --- a/src/Volo.Abp.Permissions.Domain/Volo/Abp/Permissions/PermissionStore.cs +++ b/src/Volo.Abp.Permissions.Domain/Volo/Abp/Permissions/PermissionStore.cs @@ -11,6 +11,7 @@ using Volo.Abp.Threading; namespace Volo.Abp.Permissions { + //TODO: Extract cache invalidate logic to another class public class PermissionStore : AbpServiceBase, IPermissionStore, IAsyncEventHandler>, ITransientDependency { private readonly IPermissionGrantRepository _permissionGrantRepository; diff --git a/src/Volo.Abp.Serialization/Volo.Abp.Serialization.csproj b/src/Volo.Abp.Serialization/Volo.Abp.Serialization.csproj new file mode 100644 index 0000000000..b981aed64e --- /dev/null +++ b/src/Volo.Abp.Serialization/Volo.Abp.Serialization.csproj @@ -0,0 +1,20 @@ + + + + + + netstandard2.0 + Volo.Abp.Serialization + Volo.Abp.Serialization + $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; + false + false + false + + + + + + + + diff --git a/src/Volo.Abp.Serialization/Volo.Abp.Serialization.csproj.DotSettings b/src/Volo.Abp.Serialization/Volo.Abp.Serialization.csproj.DotSettings new file mode 100644 index 0000000000..58ad6c8854 --- /dev/null +++ b/src/Volo.Abp.Serialization/Volo.Abp.Serialization.csproj.DotSettings @@ -0,0 +1,2 @@ + + CSharp71 \ No newline at end of file diff --git a/src/Volo.Abp.Serialization/Volo/Abp/Serialization/AbpSerializationModule.cs b/src/Volo.Abp.Serialization/Volo/Abp/Serialization/AbpSerializationModule.cs new file mode 100644 index 0000000000..e32cce6d64 --- /dev/null +++ b/src/Volo.Abp.Serialization/Volo/Abp/Serialization/AbpSerializationModule.cs @@ -0,0 +1,28 @@ +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Modularity; +using Volo.Abp.Reflection; + +namespace Volo.Abp.Serialization +{ + public class AbpSerializationModule : AbpModule + { + public override void PreConfigureServices(IServiceCollection services) + { + services.OnExposing(context => + { + //Register types for IObjectSerializer if implements + context.ExposedTypes.AddRange( + ReflectionHelper.GetImplementedGenericTypes( + context.ImplementationType, + typeof(IObjectSerializer<>) + ) + ); + }); + } + + public override void ConfigureServices(IServiceCollection services) + { + services.AddAssemblyOf(); + } + } +} diff --git a/src/Volo.Abp.Serialization/Volo/Abp/Serialization/Binary/BinarySerializationHelper.cs b/src/Volo.Abp.Serialization/Volo/Abp/Serialization/Binary/BinarySerializationHelper.cs new file mode 100644 index 0000000000..31a9ff280b --- /dev/null +++ b/src/Volo.Abp.Serialization/Volo/Abp/Serialization/Binary/BinarySerializationHelper.cs @@ -0,0 +1,126 @@ +using System; +using System.IO; +using System.Runtime.Serialization; +using System.Runtime.Serialization.Formatters.Binary; + +namespace Volo.Abp.Serialization.Binary +{ + /// + /// This class is used to simplify serialization/deserialization operations. + /// Uses .NET binary serialization. + /// + public static class BinarySerializationHelper + { + /// + /// Serializes an object and returns as a byte array. + /// + /// object to be serialized + /// bytes of object + public static byte[] Serialize(object obj) + { + using (var memoryStream = new MemoryStream()) + { + Serialize(obj, memoryStream); + return memoryStream.ToArray(); + } + } + + /// + /// Serializes an object into a stream. + /// + /// object to be serialized + /// Stream to serialize in + /// bytes of object + public static void Serialize(object obj, Stream stream) + { + CreateBinaryFormatter().Serialize(stream, obj); + } + + /// + /// Deserializes an object from given byte array. + /// + /// The byte array that contains object + /// deserialized object + public static object Deserialize(byte[] bytes) + { + using (var memoryStream = new MemoryStream(bytes)) + { + return Deserialize(memoryStream); + } + } + + /// + /// Deserializes an object from given stream. + /// + /// The stream that contains object + /// deserialized object + public static object Deserialize(Stream stream) + { + return CreateBinaryFormatter().Deserialize(stream); + } + + /// + /// Deserializes an object from given byte array. + /// Difference from is that; this method can also deserialize + /// types that are defined in dynamically loaded assemblies (like PlugIns). + /// + /// The byte array that contains object + /// deserialized object + public static object DeserializeExtended(byte[] bytes) + { + using (var memoryStream = new MemoryStream(bytes)) + { + return CreateBinaryFormatter(true).Deserialize(memoryStream); + } + } + + /// + /// Deserializes an object from given stream. + /// Difference from is that; this method can also deserialize + /// types that are defined in dynamically loaded assemblies (like PlugIns). + /// + /// The stream that contains object + /// deserialized object + public static object DeserializeExtended(Stream stream) + { + return CreateBinaryFormatter(true).Deserialize(stream); + } + + private static BinaryFormatter CreateBinaryFormatter(bool extended = false) + { + if (extended) + { + return new BinaryFormatter + { + //TODO: AssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple, + Binder = new ExtendedSerializationBinder() + }; + } + else + { + return new BinaryFormatter(); + } + } + + /// + /// This class is used in deserializing to allow deserializing objects that are defined + /// in assemlies that are load in runtime (like PlugIns). + /// + private sealed class ExtendedSerializationBinder : SerializationBinder + { + public override Type BindToType(string assemblyName, string typeName) + { + var toAssemblyName = assemblyName.Split(',')[0]; + foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) + { + if (assembly.FullName.Split(',')[0] == toAssemblyName) + { + return assembly.GetType(typeName); + } + } + + return Type.GetType(string.Format("{0}, {1}", typeName, assemblyName)); + } + } + } +} diff --git a/src/Volo.Abp.Serialization/Volo/Abp/Serialization/DefaultObjectSerializer.cs b/src/Volo.Abp.Serialization/Volo/Abp/Serialization/DefaultObjectSerializer.cs new file mode 100644 index 0000000000..009fab9fb2 --- /dev/null +++ b/src/Volo.Abp.Serialization/Volo/Abp/Serialization/DefaultObjectSerializer.cs @@ -0,0 +1,69 @@ +using System; +using JetBrains.Annotations; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Serialization.Binary; + +namespace Volo.Abp.Serialization +{ + public class DefaultObjectSerializer : IObjectSerializer, ITransientDependency + { + private readonly IServiceProvider _serviceProvider; + + public DefaultObjectSerializer(IServiceProvider serviceProvider) + { + _serviceProvider = serviceProvider; + } + + public virtual byte[] Serialize(T obj) + { + if (obj == null) + { + return null; + } + + //Check if a specific serializer is registered + using (var scope = _serviceProvider.CreateScope()) + { + var specificSerializer = scope.ServiceProvider.GetService>(); + if (specificSerializer != null) + { + return specificSerializer.Serialize(obj); + } + } + + return AutoSerialize(obj); + } + + [CanBeNull] + public virtual T Deserialize(byte[] bytes) + { + if (bytes == null) + { + return default; + } + + //Check if a specific serializer is registered + using (var scope = _serviceProvider.CreateScope()) + { + var specificSerializer = scope.ServiceProvider.GetService>(); + if (specificSerializer != null) + { + return specificSerializer.Deserialize(bytes); + } + } + + return AutoDeserialize(bytes); + } + + protected virtual byte[] AutoSerialize(T obj) + { + return BinarySerializationHelper.Serialize(obj); + } + + protected virtual T AutoDeserialize(byte[] bytes) + { + return (T) BinarySerializationHelper.DeserializeExtended(bytes); + } + } +} \ No newline at end of file diff --git a/src/Volo.Abp.Serialization/Volo/Abp/Serialization/IObjectSerializer.cs b/src/Volo.Abp.Serialization/Volo/Abp/Serialization/IObjectSerializer.cs new file mode 100644 index 0000000000..c8ba3ffc56 --- /dev/null +++ b/src/Volo.Abp.Serialization/Volo/Abp/Serialization/IObjectSerializer.cs @@ -0,0 +1,16 @@ +namespace Volo.Abp.Serialization +{ + public interface IObjectSerializer + { + byte[] Serialize(T obj); + + T Deserialize(byte[] bytes); + } + + public interface IObjectSerializer + { + byte[] Serialize(T obj); + + T Deserialize(byte[] bytes); + } +} diff --git a/src/Volo.Abp/Volo.Abp.csproj b/src/Volo.Abp/Volo.Abp.csproj index ced7db9c3c..ec47794004 100644 --- a/src/Volo.Abp/Volo.Abp.csproj +++ b/src/Volo.Abp/Volo.Abp.csproj @@ -24,6 +24,7 @@ + diff --git a/src/Volo.Abp/Volo/Abp/AbpCommonModule.cs b/src/Volo.Abp/Volo/Abp/AbpCommonModule.cs index 639e80fecc..9f4bb07e62 100644 --- a/src/Volo.Abp/Volo/Abp/AbpCommonModule.cs +++ b/src/Volo.Abp/Volo/Abp/AbpCommonModule.cs @@ -9,6 +9,7 @@ using Volo.Abp.Modularity; using Volo.Abp.MultiTenancy; using Volo.Abp.ObjectMapping; using Volo.Abp.Security; +using Volo.Abp.Serialization; using Volo.Abp.Session; using Volo.Abp.Settings; using Volo.Abp.Validation; @@ -29,6 +30,7 @@ namespace Volo.Abp [DependsOn(typeof(AbpApiVersioningAbstractionsModule))] [DependsOn(typeof(AbpMultiTenancyAbstractionsModule))] [DependsOn(typeof(AbpCachingModule))] + [DependsOn(typeof(AbpSerializationModule))] public class AbpCommonModule : AbpModule { public override void ConfigureServices(IServiceCollection services) diff --git a/test/Volo.Abp.Caching.Tests/Volo.Abp.Caching.Tests.csproj b/test/Volo.Abp.Caching.Tests/Volo.Abp.Caching.Tests.csproj new file mode 100644 index 0000000000..65e3abae38 --- /dev/null +++ b/test/Volo.Abp.Caching.Tests/Volo.Abp.Caching.Tests.csproj @@ -0,0 +1,24 @@ + + + + netcoreapp2.0 + latest + Volo.Abp.Caching.Tests + Volo.Abp.Caching.Tests + true + false + false + false + + + + + + + + + + + + + diff --git a/test/Volo.Abp.Caching.Tests/Volo/Abp/Caching/AbpCachingTestModule.cs b/test/Volo.Abp.Caching.Tests/Volo/Abp/Caching/AbpCachingTestModule.cs new file mode 100644 index 0000000000..410c1c58bf --- /dev/null +++ b/test/Volo.Abp.Caching.Tests/Volo/Abp/Caching/AbpCachingTestModule.cs @@ -0,0 +1,14 @@ +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Modularity; + +namespace Volo.Abp.Caching +{ + [DependsOn(typeof(AbpCachingModule))] + public class AbpCachingTestModule : AbpModule + { + public override void ConfigureServices(IServiceCollection services) + { + services.AddAssemblyOf(); + } + } +} \ No newline at end of file diff --git a/test/Volo.Abp.Caching.Tests/Volo/Abp/Caching/DistributedCache_Tests.cs b/test/Volo.Abp.Caching.Tests/Volo/Abp/Caching/DistributedCache_Tests.cs new file mode 100644 index 0000000000..45f2b21da3 --- /dev/null +++ b/test/Volo.Abp.Caching.Tests/Volo/Abp/Caching/DistributedCache_Tests.cs @@ -0,0 +1,40 @@ +using System; +using System.Threading.Tasks; +using Shouldly; +using Volo.Abp.TestBase; +using Xunit; + +namespace Volo.Abp.Caching +{ + public class DistributedCache_Tests : AbpIntegratedTest + { + [Fact] + public async Task Should_Set_Get_And_Remove_Cache_Items() + { + var personCache = GetRequiredService>(); + + var cacheKey = Guid.NewGuid().ToString(); + const string personName = "john nash"; + + //Get (not exists yet) + var cacheItem = await personCache.GetAsync(cacheKey); + cacheItem.ShouldBeNull(); + + //Set + cacheItem = new PersonCacheItem(personName); + await personCache.SetAsync(cacheKey, cacheItem); + + //Get (it should be available now + cacheItem = await personCache.GetAsync(cacheKey); + cacheItem.ShouldNotBeNull(); + cacheItem.Name.ShouldBe(personName); + + //Remove + await personCache.RemoveAsync(cacheKey); + + //Get (not exists since removed) + cacheItem = await personCache.GetAsync(cacheKey); + cacheItem.ShouldBeNull(); + } + } +} diff --git a/test/Volo.Abp.Caching.Tests/Volo/Abp/Caching/PersonCacheItem.cs b/test/Volo.Abp.Caching.Tests/Volo/Abp/Caching/PersonCacheItem.cs new file mode 100644 index 0000000000..a1011bc186 --- /dev/null +++ b/test/Volo.Abp.Caching.Tests/Volo/Abp/Caching/PersonCacheItem.cs @@ -0,0 +1,20 @@ +using System; + +namespace Volo.Abp.Caching +{ + [Serializable] + public class PersonCacheItem + { + public string Name { get; private set; } + + private PersonCacheItem() + { + + } + + public PersonCacheItem(string name) + { + Name = name; + } + } +} \ No newline at end of file diff --git a/test/Volo.Abp.Serialization.Tests/Volo.Abp.Serialization.Tests.csproj b/test/Volo.Abp.Serialization.Tests/Volo.Abp.Serialization.Tests.csproj new file mode 100644 index 0000000000..d37bf44009 --- /dev/null +++ b/test/Volo.Abp.Serialization.Tests/Volo.Abp.Serialization.Tests.csproj @@ -0,0 +1,24 @@ + + + + netcoreapp2.0 + latest + Volo.Abp.Serialization.Tests + Volo.Abp.Serialization.Tests + true + false + false + false + + + + + + + + + + + + + diff --git a/test/Volo.Abp.Serialization.Tests/Volo/Abp/Serialization/AbpSerializationTestModule.cs b/test/Volo.Abp.Serialization.Tests/Volo/Abp/Serialization/AbpSerializationTestModule.cs new file mode 100644 index 0000000000..1204bc3f2f --- /dev/null +++ b/test/Volo.Abp.Serialization.Tests/Volo/Abp/Serialization/AbpSerializationTestModule.cs @@ -0,0 +1,14 @@ +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Modularity; + +namespace Volo.Abp.Serialization +{ + [DependsOn(typeof(AbpSerializationModule))] + public class AbpSerializationTestModule : AbpModule + { + public override void ConfigureServices(IServiceCollection services) + { + services.AddAssemblyOf(); + } + } +} \ No newline at end of file diff --git a/test/Volo.Abp.Serialization.Tests/Volo/Abp/Serialization/ObjectSerializer_Tests.cs b/test/Volo.Abp.Serialization.Tests/Volo/Abp/Serialization/ObjectSerializer_Tests.cs new file mode 100644 index 0000000000..5817c78c4e --- /dev/null +++ b/test/Volo.Abp.Serialization.Tests/Volo/Abp/Serialization/ObjectSerializer_Tests.cs @@ -0,0 +1,38 @@ +using Shouldly; +using Volo.Abp.Serialization.Objects; +using Volo.Abp.TestBase; +using Xunit; + +namespace Volo.Abp.Serialization +{ + public class ObjectSerializer_Tests : AbpIntegratedTest + { + private readonly IObjectSerializer _serializer; + + public ObjectSerializer_Tests() + { + _serializer = GetRequiredService(); + } + + [Fact] + public void Should_Return_Null_For_Null_Object() + { + _serializer.Serialize(null).ShouldBeNull(); + _serializer.Deserialize((byte[])null).ShouldBeNull(); + } + + [Fact] + public void Simple_Serialize_Deserialize() + { + _serializer.Deserialize(_serializer.Serialize(new Person("john"))).Name.ShouldBe("john"); + } + + [Fact] + public void Should_Use_Specific_Serializer_If_Available() + { + _serializer.Deserialize(_serializer.Serialize(new Car("xc40"))).Name.ShouldBe("xc40-serialized-deserialized"); + } + + //TODO: Other methods + } +} diff --git a/test/Volo.Abp.Serialization.Tests/Volo/Abp/Serialization/Objects/Car.cs b/test/Volo.Abp.Serialization.Tests/Volo/Abp/Serialization/Objects/Car.cs new file mode 100644 index 0000000000..049c8cb91f --- /dev/null +++ b/test/Volo.Abp.Serialization.Tests/Volo/Abp/Serialization/Objects/Car.cs @@ -0,0 +1,20 @@ +using System; + +namespace Volo.Abp.Serialization.Objects +{ + [Serializable] + public class Car + { + public string Name { get; set; } + + private Car() + { + + } + + public Car(string name) + { + Name = name; + } + } +} diff --git a/test/Volo.Abp.Serialization.Tests/Volo/Abp/Serialization/Objects/CarSerializer.cs b/test/Volo.Abp.Serialization.Tests/Volo/Abp/Serialization/Objects/CarSerializer.cs new file mode 100644 index 0000000000..4c09a3ca93 --- /dev/null +++ b/test/Volo.Abp.Serialization.Tests/Volo/Abp/Serialization/Objects/CarSerializer.cs @@ -0,0 +1,21 @@ +using Volo.Abp.DependencyInjection; +using Volo.Abp.Serialization.Binary; + +namespace Volo.Abp.Serialization.Objects +{ + public class CarSerializer : IObjectSerializer, ITransientDependency + { + public byte[] Serialize(Car obj) + { + obj.Name += "-serialized"; + return BinarySerializationHelper.Serialize(obj); + } + + public Car Deserialize(byte[] bytes) + { + var car = (Car)BinarySerializationHelper.DeserializeExtended(bytes); + car.Name += "-deserialized"; + return car; + } + } +} \ No newline at end of file diff --git a/test/Volo.Abp.Serialization.Tests/Volo/Abp/Serialization/Objects/Person.cs b/test/Volo.Abp.Serialization.Tests/Volo/Abp/Serialization/Objects/Person.cs new file mode 100644 index 0000000000..2dcb4cf99e --- /dev/null +++ b/test/Volo.Abp.Serialization.Tests/Volo/Abp/Serialization/Objects/Person.cs @@ -0,0 +1,20 @@ +using System; + +namespace Volo.Abp.Serialization.Objects +{ + [Serializable] + public class Person + { + public string Name { get; private set; } + + private Person() + { + + } + + public Person(string name) + { + Name = name; + } + } +}