Skip to content

merge to latest #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 24 commits into from
May 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
56255f6
Change redis commandFlags to None
DannyVarod Jul 9, 2019
d3dd809
Merge pull request #40 from pub-comp/feature/redisCommandFlags
pub-comp Jul 9, 2019
7a1c415
Support cache attribute on generic method without generic parameter (…
linoyisr Jul 23, 2019
e734019
Adding pop up with postsharp install requirement (#44)
AvitalOfstein May 10, 2020
3c8d90f
Fallbacks, automatic/general invalidation, Redis Optimizations, IScop…
AwMalka May 18, 2020
809ce73
Bump System.IO.Pipelines from 4.5.0 to 4.5.1 in /WebApi (#45)
dependabot[bot] May 18, 2020
4b27550
Replaced problematic CacheAttribute interlocked initialization (#46)
ybqwerty Jan 18, 2021
1236bae
same change as in CacheAttribute init now in CacheListAttribute
Jan 19, 2021
202c7e5
Merge pull request #47 from pub-comp/hotfix/aop-list-init
ybqwerty Jan 19, 2021
4ba1b87
Update License.txt
amitla Jan 31, 2021
ee400cc
Merge pull request #48 from pub-comp/feature/dual-license
ybqwerty Jan 31, 2021
61f78ff
dispose of previous inner (in-memory) cache when calling ClearAll()
Jul 25, 2021
593bd18
Merge pull request #49 from pub-comp/hotfix/dispose-old-inmemorycache
ybqwerty Jul 26, 2021
c52840d
upgrade PostSharp & use PSerializable
NoahLerner Jul 4, 2022
1b633bf
fix build
NoahLerner Jul 4, 2022
47117ea
upgrade version of AOPCaching
NoahLerner Jul 4, 2022
92134d1
Merge pull request #58 from NoahLerner/feature/upgrade-postsharp-supp…
pub-comp Jul 11, 2022
99a7951
use PSerializable for support .Net 6.0
Sep 1, 2022
9bc2e0f
version 5.0.4
Sep 4, 2022
cd66e7a
Merge pull request #62 from MikaelTap/master
pub-comp Sep 6, 2022
9ab58ea
reverting changes done in CacheAttribute and CacheListAttribute.
Oct 31, 2022
e9d196c
Merge pull request #64 from pub-comp/release/v.5.0.5
pub-comp Oct 31, 2022
a344259
breaking changes -
Nov 2, 2022
5dc2cbc
Merge pull request #63 from pub-comp/release/v.6.0.0
pub-comp Nov 2, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions AopCaching.UnitTests/AopCacheTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,26 @@ public void TestCacheWithImplicitName()
Assert.AreEqual(2, cache1.Misses);
}

[TestMethod]
public void TestMissingNameCache()
{
var service = new Service2();
var result = service.MethodToCache0();
Assert.AreEqual(1, result);
result = service.MethodToCache0();
Assert.AreEqual(2, result);
}

[TestMethod]
public async Task TestMissingNameCacheAsync()
{
var service = new Service2();
var result = await service.MethodToCache0Async();
Assert.AreEqual(1, result);
result = await service.MethodToCache0Async();
Assert.AreEqual(2, result);
}

[TestMethod]
public void TestNamedCache1()
{
Expand Down Expand Up @@ -280,6 +300,51 @@ public void TestCacheWithGenericClass()
Assert.AreEqual(4, cache3.Misses);
}

[TestMethod]
public void TestCacheWithGenericMethodAndWithoutGenericParameter()
{
Assert.AreEqual(0, cache3.Hits);
Assert.AreEqual(0, cache3.Misses);

var result1 = new GenericService<int>().GenericMethodToCache<Enum1>();
Assert.AreEqual(0, cache3.Hits);
Assert.AreEqual(2, cache3.Misses);
Assert.AreEqual(result1, (int)Enum1.Value);

var result2 = new GenericService<int>().GenericMethodToCache<Enum1>();
Assert.AreEqual(1, cache3.Hits);
Assert.AreEqual(2, cache3.Misses);
Assert.AreEqual(result2, (int)Enum1.Value);

var result3 = new GenericService<int>().GenericMethodToCache<Enum2>();
Assert.AreEqual(1, cache3.Hits);
Assert.AreEqual(4, cache3.Misses);
Assert.AreEqual(result3, (int)Enum2.Value);
}

[TestMethod]
public void TestCacheWithGenericMethodAndWithoutGenericReturnValue()
{
Assert.AreEqual(0, cache3.Hits);
Assert.AreEqual(0, cache3.Misses);

new GenericService1<Enum1>().GenericMethodToCacheWithGenericReturnType((int) Enum1.Value);
Assert.AreEqual(0, cache3.Hits);
Assert.AreEqual(2, cache3.Misses);

new GenericService1<Enum1>().GenericMethodToCacheWithGenericReturnType((int)Enum1.Value);
Assert.AreEqual(1, cache3.Hits);
Assert.AreEqual(2, cache3.Misses);

new GenericService1<Enum2>().GenericMethodToCacheWithGenericReturnType((int)Enum1.Value);
Assert.AreEqual(1, cache3.Hits);
Assert.AreEqual(4, cache3.Misses);

new GenericService1<Enum2>().GenericMethodToCacheWithGenericReturnType((int)Enum2.Value);
Assert.AreEqual(1, cache3.Hits);
Assert.AreEqual(6, cache3.Misses);
}

[TestMethod]
public async Task TestCacheWithGenericAsyncClass()
{
Expand Down
2 changes: 1 addition & 1 deletion AopCaching.UnitTests/AopCaching.UnitTests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<ItemGroup>
<PackageReference Include="MSTest.TestAdapter" Version="1.2.0" />
<PackageReference Include="MSTest.TestFramework" Version="1.2.0" />
<PackageReference Include="PostSharp" Version="6.0.28" />
<PackageReference Include="PostSharp" Version="6.10.13" />
<PackageReference Include="System.Runtime.Caching" Version="4.5.0" />
</ItemGroup>
<ItemGroup>
Expand Down
20 changes: 20 additions & 0 deletions AopCaching.UnitTests/AopMultiCacheTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,26 @@ public void TestInitialize()
cache1.ClearAll();
}

[TestMethod]
public void TestMultiMissingCache()
{
var service = new MultiService();
var results = service.GetItemsNoCache(new[] { "k1" });
Assert.AreEqual("1", results.First().Value);
results = service.GetItemsNoCache(new[] { "k1" });
Assert.AreEqual("2", results.First().Value);
}

[TestMethod]
public async Task TestMultiMissingCacheAsync()
{
var service = new MultiService();
var results = await service.GetItemsNoCacheAsync(new[] { "k1" });
Assert.AreEqual("1", results.First().Value);
results = await service.GetItemsNoCacheAsync(new[] { "k1" });
Assert.AreEqual("2", results.First().Value);
}

[TestMethod]
public void TestMultiCacheWith1Items()
{
Expand Down
28 changes: 28 additions & 0 deletions AopCaching.UnitTests/Mocks/GenericService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,34 @@ public string MethodToCache1(int id, [DoNotIncludeInCacheKey]object obj)
return id.ToString() + (obj != null ? obj.GetHashCode() : 0).ToString();
}

[Cache]
public int GenericMethodToCache<TEnum>()
where TEnum : struct
{
if (typeof(TEnum) == typeof(Enum1))
return (int)Enum1.Value;
return (int)Enum2.Value;
}

public readonly double ConstValue = 4.0;
}

public class GenericService1<TEnum> where TEnum : struct
{
[Cache]
public TEnum GenericMethodToCacheWithGenericReturnType(int value)
{
return new TEnum();
}
}

public enum Enum1
{
Value = 1
}

public enum Enum2
{
Value = 3
}
}
4 changes: 2 additions & 2 deletions AopCaching.UnitTests/Mocks/MockCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,12 +97,12 @@ protected override bool TryGetInner<TValue>(string key, out TValue value)
{
hits++;
// ReSharper disable once CanBeReplacedWithTryCastAndCheckForNull
value = item.Value is TValue ? (TValue)item.Value : default(TValue);
value = item.Value is TValue ? (TValue)item.Value : default;
return true;
}

misses++;
value = default(TValue);
value = default;
return false;
}

Expand Down
17 changes: 17 additions & 0 deletions AopCaching.UnitTests/Mocks/MultiService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,23 @@ namespace PubComp.Caching.AopCaching.UnitTests.Mocks
{
public class MultiService
{
private int getItemsNoCacheCounter;

[CacheList("CacheMissing", typeof(MockDataKeyConverter))]
public IList<MockData> GetItemsNoCache(IList<string> keys)
{
++getItemsNoCacheCounter;
return new List<MockData> { new MockData { Id = keys.FirstOrDefault(), Value = getItemsNoCacheCounter.ToString() } };
}

[CacheList("CacheMissing", typeof(MockDataKeyConverter))]
public async Task<IList<MockData>> GetItemsNoCacheAsync(IList<string> keys)
{
++getItemsNoCacheCounter;
await Task.Delay(10);
return new List<MockData> { new MockData { Id = keys.FirstOrDefault(), Value = getItemsNoCacheCounter.ToString() } };
}

[CacheList(typeof(MockDataKeyConverter))]
public IList<MockData> GetItems(IList<string> keys)
{
Expand Down
15 changes: 15 additions & 0 deletions AopCaching.UnitTests/Mocks/Service2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,21 @@ namespace PubComp.Caching.AopCaching.UnitTests.Mocks
{
public class Service2
{
private int methodToCache0Counter;

[Cache("CacheMissing")]
public int MethodToCache0()
{
return ++methodToCache0Counter;
}

[Cache("CacheMissing")]
public async Task<int> MethodToCache0Async()
{
await Task.Delay(10);
return ++methodToCache0Counter;
}

[Cache("localCache")]
public IEnumerable<string> MethodToCache1()
{
Expand Down
52 changes: 27 additions & 25 deletions AopCaching/AopCaching.csproj
Original file line number Diff line number Diff line change
@@ -1,26 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<AssemblyName>PubComp.Caching.AopCaching</AssemblyName>
<RootNamespace>PubComp.Caching.AopCaching</RootNamespace>
<Version>4.4.0</Version>
<!--Only change AssemblyVersion for major versions!--><AssemblyVersion>4.1.1.0</AssemblyVersion>
<FileVersion>4.4.0.0</FileVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<NoWarn>1701;1702;1591</NoWarn>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<NoWarn>1701;1702;1591</NoWarn>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="PostSharp" Version="6.0.28" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Core\Core.csproj" />
</ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command="&quot;$(SolutionDir).NuGetPack\NuGetPack.exe&quot; &quot;$(ProjectPath)&quot; &quot;$(TargetPath)&quot; $(ConfigurationName)" />
</Target>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<AssemblyName>PubComp.Caching.AopCaching</AssemblyName>
<RootNamespace>PubComp.Caching.AopCaching</RootNamespace>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Version>6.0.0</Version>
<AssemblyVersion>6.0.0.0</AssemblyVersion>
<FileVersion>6.0.0.0</FileVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<NoWarn>1701;1702;1591</NoWarn>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<NoWarn>1701;1702;1591</NoWarn>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="NLog" Version="4.5.10" />
<PackageReference Include="PostSharp" Version="6.10.13" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Core\Core.csproj" />
</ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command="&quot;$(SolutionDir).NuGetPack\NuGetPack.exe&quot; &quot;$(ProjectPath)&quot; &quot;$(TargetPath)&quot; $(ConfigurationName)" />
</Target>
</Project>
60 changes: 35 additions & 25 deletions AopCaching/CacheAttribute.cs
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
using System;
using System.Linq;
using System.Threading;
using NLog;
using PostSharp.Aspects;
using PostSharp.Serialization;
using PubComp.Caching.Core;
using PubComp.Caching.Core.Attributes;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using PubComp.Caching.Core.Attributes;

namespace PubComp.Caching.AopCaching
{
[Serializable]
[PSerializable]
public class CacheAttribute : MethodInterceptionAspect
{
private string cacheName;
private ICache cache;
private long initialized = 0L;
private string className;
private string methodName;
private string[] parameterTypeNames;
Expand All @@ -32,7 +32,7 @@ public CacheAttribute(string cacheName)
this.cacheName = cacheName;
}

public sealed override void CompileTimeInitialize(System.Reflection.MethodBase method, AspectInfo aspectInfo)
public sealed override void CompileTimeInitialize(MethodBase method, AspectInfo aspectInfo)
{
var type = method.DeclaringType;

Expand Down Expand Up @@ -64,15 +64,17 @@ public sealed override void CompileTimeInitialize(System.Reflection.MethodBase m

public sealed override void OnInvoke(MethodInterceptionArgs args)
{
if (Interlocked.Read(ref initialized) == 0L)
if (this.cache == null)
{
this.cache = CacheManager.GetCache(this.cacheName);
Interlocked.Exchange(ref initialized, 1L);
if (this.cache == null)
{
LogManager.GetCurrentClassLogger().Warn($"AOP cache [{this.cacheName}] is not initialized, define NoCache if needed!");
}
}

var cacheToUse = this.cache;

if (cacheToUse == null)
if (!cacheToUse.IsUseable())
{
base.OnInvoke(args);
return;
Expand All @@ -87,25 +89,32 @@ public sealed override void OnInvoke(MethodInterceptionArgs args)
/// <inheritdoc />
public sealed override async Task OnInvokeAsync(MethodInterceptionArgs args)
{
if (Interlocked.Read(ref initialized) == 0L)
if (this.cache == null)
{
this.cache = CacheManager.GetCache(this.cacheName);
Interlocked.Exchange(ref initialized, 1L);
if (this.cache == null)
{
LogManager.GetCurrentClassLogger().Warn($"AOP cache [{this.cacheName}] is not initialized, define NoCache if needed!");
}
}

var cacheToUse = this.cache;

if (cacheToUse == null)
{
await base.OnInvokeAsync(args);
}
else
if (!cacheToUse.IsUseable())
{
var key = GetCacheKey(args);
var result = await cacheToUse.GetAsync(key, async () => { await base.OnInvokeAsync(args); return args.ReturnValue; });
var returnType = GetReturnType(args.Method);
args.ReturnValue = SafeCasting.CastTo(returnType, result);
await base.OnInvokeAsync(args).ConfigureAwait(false);
return;
}

var key = GetCacheKey(args);
var result = await cacheToUse
.GetAsync(key, async () =>
{
await base.OnInvokeAsync(args).ConfigureAwait(false);
return args.ReturnValue;
})
.ConfigureAwait(false);
var returnType = GetReturnType(args.Method);
args.ReturnValue = SafeCasting.CastTo(returnType, result);
}

private string GetCacheKey(MethodInterceptionArgs args)
Expand All @@ -118,10 +127,11 @@ private string GetCacheKey(MethodInterceptionArgs args)
? this.parameterTypeNames
: args.Method.GetParameters().Select(p => p.ParameterType.FullName).ToArray();

var genericArgumentTypeNames = args.Method.GetGenericArguments().Select(a => a.FullName).ToArray();

var parameterValues = args.Arguments.Where((arg, index) => !this.indexesNotToCache.Contains(index)).ToArray();

var key =
new CacheKey(classNameNonGeneric, this.methodName, parameterTypeNamesNonGeneric, parameterValues).ToString();
var key = new CacheKey(classNameNonGeneric, this.methodName, parameterTypeNamesNonGeneric, parameterValues, genericArgumentTypeNames).ToString();
return key;
}

Expand Down
Loading