Skip to content

Commit 3a568d4

Browse files
authored
Merge pull request #15 from SpatialFocus/feat/inherited-cachegetterproperty
Support for inherited IMemoryCache property, closes #2
2 parents 43b6948 + 8c1b149 commit 3a568d4

File tree

10 files changed

+157
-29
lines changed

10 files changed

+157
-29
lines changed

SpatialFocus.MethodCache.Fody.sln

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SpatialFocus.MethodCache.Sa
3838
{81703F57-025F-42C4-AE8B-568E2F56CCE2} = {81703F57-025F-42C4-AE8B-568E2F56CCE2}
3939
EndProjectSection
4040
EndProject
41+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SpatialFocus.MethodCache.TestAssembly2", "src\SpatialFocus.MethodCache.TestAssembly2\SpatialFocus.MethodCache.TestAssembly2.csproj", "{766C91B4-5753-4B31-9FBF-684D6754D2DA}"
42+
EndProject
4143
Global
4244
GlobalSection(SolutionConfigurationPlatforms) = preSolution
4345
Debug|Any CPU = Debug|Any CPU
@@ -72,6 +74,10 @@ Global
7274
{E03D9328-B71F-4451-9956-6D28186F84A7}.Debug|Any CPU.Build.0 = Debug|Any CPU
7375
{E03D9328-B71F-4451-9956-6D28186F84A7}.Release|Any CPU.ActiveCfg = Release|Any CPU
7476
{E03D9328-B71F-4451-9956-6D28186F84A7}.Release|Any CPU.Build.0 = Release|Any CPU
77+
{766C91B4-5753-4B31-9FBF-684D6754D2DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
78+
{766C91B4-5753-4B31-9FBF-684D6754D2DA}.Debug|Any CPU.Build.0 = Debug|Any CPU
79+
{766C91B4-5753-4B31-9FBF-684D6754D2DA}.Release|Any CPU.ActiveCfg = Release|Any CPU
80+
{766C91B4-5753-4B31-9FBF-684D6754D2DA}.Release|Any CPU.Build.0 = Release|Any CPU
7581
EndGlobalSection
7682
GlobalSection(SolutionProperties) = preSolution
7783
HideSolutionNode = FALSE
@@ -84,6 +90,7 @@ Global
8490
{C47814DC-272E-4FB8-A97C-2B6C75F60C76} = {674F705E-E459-490B-B536-3F750485AE33}
8591
{88A8C843-A479-42B8-AAF6-8F816C660515} = {674F705E-E459-490B-B536-3F750485AE33}
8692
{E03D9328-B71F-4451-9956-6D28186F84A7} = {674F705E-E459-490B-B536-3F750485AE33}
93+
{766C91B4-5753-4B31-9FBF-684D6754D2DA} = {674F705E-E459-490B-B536-3F750485AE33}
8794
EndGlobalSection
8895
GlobalSection(ExtensibilityGlobals) = postSolution
8996
SolutionGuid = {1a3946bb-e6d6-4999-932a-807a80bc0cdb}

src/SpatialFocus.MethodCache.Fody/Extensions/TypeDefinitionExtension.cs

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace SpatialFocus.MethodCache.Fody.Extensions
66
{
77
using System;
8+
using System.Collections.Generic;
89
using System.Linq;
910
using Mono.Cecil;
1011

@@ -39,7 +40,24 @@ public static bool IsEligibleForWeaving(this TypeDefinition typeDefinition, Refe
3940
throw new ArgumentNullException(nameof(references));
4041
}
4142

42-
return typeDefinition.Properties.Where(propertyDefinition =>
43+
bool isEligibleForWeaving = typeDefinition.TryGetCacheGetterProperty(references)?.Count == 1;
44+
45+
return isEligibleForWeaving;
46+
}
47+
48+
public static List<PropertyDefinition> TryGetCacheGetterProperty(this TypeDefinition typeDefinition, References references)
49+
{
50+
if (typeDefinition == null)
51+
{
52+
throw new ArgumentNullException(nameof(typeDefinition));
53+
}
54+
55+
if (references == null)
56+
{
57+
throw new ArgumentNullException(nameof(references));
58+
}
59+
60+
List<PropertyDefinition> properties = typeDefinition.Properties.Where(propertyDefinition =>
4361
{
4462
TypeDefinition propertyTypeDefinition = propertyDefinition.PropertyType.Resolve();
4563
TypeDefinition memoryCacheInterface = references.MemoryCacheInterface.Resolve();
@@ -61,7 +79,15 @@ public static bool IsEligibleForWeaving(this TypeDefinition typeDefinition, Refe
6179

6280
return false;
6381
})
64-
.Count() == 1;
82+
.ToList();
83+
84+
if (!properties.Any() && typeDefinition.BaseType != null)
85+
{
86+
TypeDefinition baseTypeDefinition = typeDefinition.BaseType.Resolve();
87+
properties = baseTypeDefinition.TryGetCacheGetterProperty(references);
88+
}
89+
90+
return properties;
6591
}
6692

6793
public static CustomAttribute TryGetCacheAttribute(this TypeDefinition typeDefinition, References references)

src/SpatialFocus.MethodCache.Fody/MemoryCache.cs

Lines changed: 5 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -51,37 +51,16 @@ public static MethodReference GetCacheGetterMethod(ClassWeavingContext classWeav
5151
}
5252

5353
// TODO: Check if this can be inherited, extract to class level
54-
List<PropertyDefinition> propertyDefinitions = classWeavingContext.TypeDefinition.Properties.Where(definition =>
55-
{
56-
TypeDefinition typeDefinition = definition.PropertyType.Resolve();
57-
TypeDefinition memoryCacheInterface = classWeavingContext.References.MemoryCacheInterface.Resolve();
58-
59-
if (definition.GetMethod.IsStatic)
60-
{
61-
return false;
62-
}
63-
64-
if (typeDefinition.IsInterface && typeDefinition.Equals(memoryCacheInterface))
65-
{
66-
return true;
67-
}
68-
69-
if (typeDefinition.Interfaces.Any(x => x.InterfaceType == memoryCacheInterface))
70-
{
71-
return true;
72-
}
73-
74-
return false;
75-
})
76-
.ToList();
54+
List<PropertyDefinition> propertyDefinitions =
55+
classWeavingContext.TypeDefinition.TryGetCacheGetterProperty(classWeavingContext.References);
7756

7857
// TODO: Also check fields
79-
if (propertyDefinitions.Count != 1)
58+
if (propertyDefinitions == null || propertyDefinitions.Count != 1)
8059
{
81-
throw new WeavingException("Property not found");
60+
throw new WeavingException("Cache Property not found or multiple properties found.");
8261
}
8362

84-
MethodDefinition methodDefinition = propertyDefinitions.Single().GetMethod;
63+
MethodReference methodDefinition = classWeavingContext.TypeDefinition.Module.ImportReference(propertyDefinitions.Single().GetMethod);
8564

8665
if (methodDefinition.DeclaringType.GenericParameters.Any())
8766
{

src/SpatialFocus.MethodCache.Fody/ModuleWeaver.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public override void Execute()
3232
if (!weavingCandidate.ClassDefinition.IsEligibleForWeaving(references))
3333
{
3434
WriteWarning(
35-
$"Class {weavingCandidate.ClassDefinition.Name} contains [Cache] attribute but does not contain a single non-inherited property implementing IMemoryCache interface");
35+
$"Class {weavingCandidate.ClassDefinition.Name} contains [Cache] attribute but does not contain a single property implementing IMemoryCache interface");
3636
continue;
3737
}
3838

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// <copyright file="DerivedTestClass.cs" company="Spatial Focus GmbH">
2+
// Copyright (c) Spatial Focus GmbH. All rights reserved.
3+
// </copyright>
4+
5+
namespace SpatialFocus.MethodCache.TestAssembly
6+
{
7+
using Microsoft.Extensions.Caching.Memory;
8+
9+
[Cache]
10+
public class DerivedTestClass : BaseClass
11+
{
12+
public DerivedTestClass(IMemoryCache memoryCache) : base(memoryCache)
13+
{
14+
}
15+
16+
#pragma warning disable CA1822 // Mark members as static
17+
public int Add(int a, int b)
18+
{
19+
return a + b;
20+
}
21+
#pragma warning restore CA1822 // Mark members as static
22+
}
23+
24+
#pragma warning disable SA1402 // File may only contain a single type
25+
public class BaseClass
26+
{
27+
public BaseClass(IMemoryCache memoryCache)
28+
{
29+
MemoryCache = memoryCache;
30+
}
31+
32+
public IMemoryCache MemoryCache { get; }
33+
}
34+
#pragma warning restore SA1402 // File may only contain a single type
35+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// <copyright file="DerivedTestClass2.cs" company="Spatial Focus GmbH">
2+
// Copyright (c) Spatial Focus GmbH. All rights reserved.
3+
// </copyright>
4+
5+
namespace SpatialFocus.MethodCache.TestAssembly
6+
{
7+
using Microsoft.Extensions.Caching.Memory;
8+
9+
[Cache]
10+
public class DerivedTestClass2 : TestAssembly2.BaseClass
11+
{
12+
public DerivedTestClass2(IMemoryCache memoryCache) : base(memoryCache)
13+
{
14+
}
15+
16+
#pragma warning disable CA1822 // Mark members as static
17+
public int Add(int a, int b)
18+
{
19+
return a + b;
20+
}
21+
#pragma warning restore CA1822 // Mark members as static
22+
}
23+
}

src/SpatialFocus.MethodCache.TestAssembly/SpatialFocus.MethodCache.TestAssembly.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
</ItemGroup>
1111

1212
<ItemGroup>
13+
<ProjectReference Include="..\SpatialFocus.MethodCache.TestAssembly2\SpatialFocus.MethodCache.TestAssembly2.csproj" />
1314
<ProjectReference Include="..\SpatialFocus.MethodCache\SpatialFocus.MethodCache.csproj" />
1415
</ItemGroup>
1516

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// <copyright file="BaseClass.cs" company="Spatial Focus GmbH">
2+
// Copyright (c) Spatial Focus GmbH. All rights reserved.
3+
// </copyright>
4+
5+
namespace SpatialFocus.MethodCache.TestAssembly2
6+
{
7+
using Microsoft.Extensions.Caching.Memory;
8+
9+
public class BaseClass
10+
{
11+
public BaseClass(IMemoryCache memoryCache)
12+
{
13+
MemoryCache = memoryCache;
14+
}
15+
16+
public IMemoryCache MemoryCache { get; }
17+
}
18+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>netstandard2.0</TargetFramework>
5+
</PropertyGroup>
6+
7+
<ItemGroup>
8+
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="3.1.9" />
9+
</ItemGroup>
10+
11+
</Project>

src/SpatialFocus.MethodCache.Tests/MemoryCacheBasicTests.cs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,5 +83,33 @@ public void BasicTest4NoCache()
8383
Assert.Equal(0, mockMemoryCache.CountSets);
8484
Assert.Equal(0, mockMemoryCache.CountGets);
8585
}
86+
87+
[Fact]
88+
public void BasicTest5DerivedClass()
89+
{
90+
using MockMemoryCache mockMemoryCache = MockMemoryCache.Default;
91+
92+
dynamic instance = TestHelpers.CreateInstance<DerivedTestClass>(MemoryCacheBasicTests.TestResult.Assembly, mockMemoryCache);
93+
94+
dynamic result = instance.Add(1, 2);
95+
96+
Assert.Equal(3, result);
97+
Assert.Equal(1, mockMemoryCache.CountSets);
98+
Assert.Equal(1, mockMemoryCache.CountGets);
99+
}
100+
101+
[Fact]
102+
public void BasicTest6DerivedClass()
103+
{
104+
using MockMemoryCache mockMemoryCache = MockMemoryCache.Default;
105+
106+
dynamic instance = TestHelpers.CreateInstance<DerivedTestClass2>(MemoryCacheBasicTests.TestResult.Assembly, mockMemoryCache);
107+
108+
dynamic result = instance.Add(1, 2);
109+
110+
Assert.Equal(3, result);
111+
Assert.Equal(1, mockMemoryCache.CountSets);
112+
Assert.Equal(1, mockMemoryCache.CountGets);
113+
}
86114
}
87115
}

0 commit comments

Comments
 (0)