Skip to content

Commit f5b61b7

Browse files
committed
Merge branch 'dev'
2 parents 6de147b + 327938d commit f5b61b7

14 files changed

+227
-111
lines changed

AspectCore/AspectCore.csproj

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
<Description>Aspect Oriented Programming Core Library With DispatchProxy in .NET Core</Description>
77
<RepositoryUrl>https://github.com/yoldascevik/AspectCore</RepositoryUrl>
88
<PackageProjectUrl>https://github.com/yoldascevik/AspectCore</PackageProjectUrl>
9-
<Version>1.1.3</Version>
10-
<PackageVersion>1.1.3</PackageVersion>
9+
<Version>1.2</Version>
10+
<PackageVersion>1.2</PackageVersion>
1111
</PropertyGroup>
1212

1313
<PropertyGroup>
@@ -18,4 +18,16 @@
1818
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.1.8" />
1919
</ItemGroup>
2020

21+
<ItemGroup>
22+
<Compile Remove="out\**" />
23+
</ItemGroup>
24+
25+
<ItemGroup>
26+
<EmbeddedResource Remove="out\**" />
27+
</ItemGroup>
28+
29+
<ItemGroup>
30+
<None Remove="out\**" />
31+
</ItemGroup>
32+
2133
</Project>

AspectCore/Aspects/AspectAttribute.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
namespace AspectCore.Aspects
55
{
6-
[AttributeUsage(AttributeTargets.Method)]
6+
[AttributeUsage(AttributeTargets.Interface | AttributeTargets.Method)]
77
public abstract class AspectAttribute: Attribute, IAspect, IAspectAsync
88
{
99
public virtual int Order => 1;

AspectCore/Decorators/AspectDecorator.cs

Lines changed: 52 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,21 @@
88

99
namespace AspectCore.Decorators
1010
{
11-
public class AspectDecorator<TDecorated>: DispatchProxyAsync
11+
public class AspectDecorator<TDecorated> : DispatchProxyAsync
1212
{
1313
private TDecorated _decorated;
1414
private IServiceProvider _serviceProvider;
15-
15+
1616
public static TDecorated Create(TDecorated decorated, IServiceProvider serviceProvider)
1717
{
1818
object proxy = Create<TDecorated, AspectDecorator<TDecorated>>();
19-
((AspectDecorator<TDecorated>)proxy).SetParameters(decorated, serviceProvider);
20-
return (TDecorated)proxy;
19+
((AspectDecorator<TDecorated>) proxy).SetParameters(decorated, serviceProvider);
20+
return (TDecorated) proxy;
2121
}
2222

2323
public override object Invoke(MethodInfo method, object[] args)
2424
{
25-
if (method == null)
26-
throw new ArgumentNullException(nameof(method));
27-
28-
List<AspectAttribute> aspects = method.GetCustomAttributes<AspectAttribute>(true).OrderBy(x => x.Order).ToList();
25+
List<AspectAttribute> aspects = GetAspectAttributesFromMethodInfo(method);
2926
if (!aspects.Any())
3027
{
3128
return method.Invoke(_decorated, args);
@@ -39,8 +36,7 @@ public override object Invoke(MethodInfo method, object[] args)
3936

4037
try
4138
{
42-
if (methodExecutionArgs.ReturnValue == null)
43-
methodExecutionArgs.ReturnValue = method.Invoke(_decorated, args);
39+
methodExecutionArgs.ReturnValue ??= method.Invoke(_decorated, args);
4440

4541
// OnSuccess
4642
aspects.ForEach(attribute => attribute
@@ -68,111 +64,101 @@ public override object Invoke(MethodInfo method, object[] args)
6864

6965
public override async Task InvokeAsync(MethodInfo method, object[] args)
7066
{
71-
if (method == null)
72-
throw new ArgumentNullException(nameof(method));
73-
74-
List<AspectAttribute> aspects = method.GetCustomAttributes<AspectAttribute>(true).OrderBy(x => x.Order).ToList();
67+
List<AspectAttribute> aspects = GetAspectAttributesFromMethodInfo(method);
7568
if (!aspects.Any())
7669
{
77-
await (Task) method.Invoke(_decorated, args);
70+
await (Task) method?.Invoke(_decorated, args);
7871
return;
7972
}
8073

8174
// OnBefore
8275
var methodExecutionArgs = new MethodExecutionArgs(method, args);
83-
84-
foreach (var aspect in aspects)
85-
{
86-
await aspect.LoadDependencies(_serviceProvider)
87-
.OnBeforeAsync(methodExecutionArgs);
88-
}
89-
76+
aspects.ForEach(async attribute => await attribute
77+
.LoadDependencies(_serviceProvider)
78+
.OnBeforeAsync(methodExecutionArgs));
79+
9080
try
9181
{
92-
await (Task) method.Invoke(_decorated, args);
82+
await (Task) method?.Invoke(_decorated, args);
9383

9484
// OnSuccess
95-
foreach (var aspect in aspects)
96-
{
97-
await aspect.LoadDependencies(_serviceProvider)
98-
.OnSuccessAsync(methodExecutionArgs);
99-
}
85+
aspects.ForEach(async attribute => await attribute
86+
.LoadDependencies(_serviceProvider)
87+
.OnSuccessAsync(methodExecutionArgs));
10088
}
10189
catch (Exception exception)
10290
{
10391
// OnException
10492
methodExecutionArgs.Exception = exception;
105-
foreach (var aspect in aspects)
106-
{
107-
await aspect.LoadDependencies(_serviceProvider)
108-
.OnExceptionAsync(methodExecutionArgs);
109-
}
93+
aspects.ForEach(async attribute => await attribute
94+
.LoadDependencies(_serviceProvider)
95+
.OnExceptionAsync(methodExecutionArgs));
11096
}
11197
finally
11298
{
11399
// OnAfter
114-
foreach (var aspect in aspects)
115-
{
116-
await aspect.LoadDependencies(_serviceProvider)
117-
.OnAfterAsync(methodExecutionArgs);
118-
}
100+
aspects.ForEach(async attribute => await attribute
101+
.LoadDependencies(_serviceProvider)
102+
.OnAfterAsync(methodExecutionArgs));
119103
}
120104
}
121105

122106
public override async Task<T> InvokeAsyncT<T>(MethodInfo method, object[] args)
123-
{
124-
if (method == null)
125-
throw new ArgumentNullException(nameof(method));
126-
127-
List<AspectAttribute> aspects = method.GetCustomAttributes<AspectAttribute>(true).OrderBy(x => x.Order).ToList();
107+
{
108+
List<AspectAttribute> aspects = GetAspectAttributesFromMethodInfo(method);
128109
if (!aspects.Any())
129110
{
130-
return await (Task<T>) method.Invoke(_decorated, args);
111+
return await (Task<T>) method?.Invoke(_decorated, args);
131112
}
132113

133114
// OnBefore
134115
var methodExecutionArgs = new MethodExecutionArgs(method, args);
135-
foreach (var aspect in aspects)
136-
{
137-
await aspect.LoadDependencies(_serviceProvider)
138-
.OnBeforeAsync(methodExecutionArgs);
139-
}
116+
aspects.ForEach(async attribute => await attribute
117+
.LoadDependencies(_serviceProvider)
118+
.OnBeforeAsync(methodExecutionArgs));
140119

141120
try
142121
{
143-
if (methodExecutionArgs?.ReturnValue == null)
144-
methodExecutionArgs.ReturnValue = await (Task<T>) method.Invoke(_decorated, args);
122+
methodExecutionArgs.ReturnValue ??= await (Task<T>) method?.Invoke(_decorated, args);
145123

146124
// OnSuccess
147-
foreach (var aspect in aspects)
148-
{
149-
await aspect.LoadDependencies(_serviceProvider)
150-
.OnSuccessAsync(methodExecutionArgs);
151-
}
125+
aspects.ForEach(async attribute => await attribute
126+
.LoadDependencies(_serviceProvider)
127+
.OnSuccessAsync(methodExecutionArgs));
152128
}
153129
catch (Exception exception)
154130
{
155131
// OnException
156132
methodExecutionArgs.Exception = exception;
157-
foreach (var aspect in aspects)
158-
{
159-
await aspect.LoadDependencies(_serviceProvider)
160-
.OnExceptionAsync(methodExecutionArgs);
161-
}
133+
aspects.ForEach(async attribute => await attribute
134+
.LoadDependencies(_serviceProvider)
135+
.OnExceptionAsync(methodExecutionArgs));
162136
}
163137
finally
164138
{
165139
// OnAfter
166-
foreach (var aspect in aspects)
167-
{
168-
await aspect.LoadDependencies(_serviceProvider)
169-
.OnAfterAsync(methodExecutionArgs);
170-
}
140+
aspects.ForEach(async attribute => await attribute
141+
.LoadDependencies(_serviceProvider)
142+
.OnAfterAsync(methodExecutionArgs));
171143
}
172144

173145
return (T) methodExecutionArgs.ReturnValue;
174146
}
175147

148+
private List<AspectAttribute> GetAspectAttributesFromMethodInfo(MethodInfo method)
149+
{
150+
if (method == null)
151+
throw new ArgumentNullException(nameof(method));
152+
153+
IEnumerable<AspectAttribute> aspectAttributes = method.GetCustomAttributes<AspectAttribute>(true);
154+
if (method.DeclaringType != null)
155+
{
156+
aspectAttributes = aspectAttributes.Concat(method.DeclaringType.GetCustomAttributes<AspectAttribute>(true));
157+
}
158+
159+
return aspectAttributes.Distinct().OrderBy(attr => attr.Order).ToList();
160+
}
161+
176162
private void SetParameters(TDecorated decorated, IServiceProvider serviceProvider)
177163
{
178164
_decorated = decorated ?? throw new ArgumentNullException(nameof(decorated));

AspectCore/DispatchProxy/AsyncDispatchProxyGenerator.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Licensed to the .NET Foundation under one or more agreements.
1+
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33
// See the LICENSE file in the project root for more information.
44

@@ -12,6 +12,7 @@
1212
using System.Threading;
1313
using System.Threading.Tasks;
1414
using Type = System.Type;
15+
// ReSharper disable All
1516

1617
namespace AspectCore.DispatchProxy
1718
{

AspectCore/ServiceCollectionExtension.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,9 @@ public static IServiceCollection DecorateAllInterfacesUsingAspect(this IServiceC
6060
throw new ArgumentNullException(nameof(assembly));
6161

6262
Type[] assignableInterfaceTypes = assembly.GetTypes()
63-
.Where(t => t.IsInterface &&
64-
t.GetMethods().Any(method => method.GetCustomAttribute<AspectAttribute>() != null))
63+
.Where(t => t.IsInterface && (
64+
t.GetCustomAttribute<AspectAttribute>() != null ||
65+
t.GetMethods().Any(method => method.GetCustomAttribute<AspectAttribute>() != null)))
6566
.ToArray();
6667

6768
return services.DescribeAll(assignableInterfaceTypes);

Test/AspectCore.Test.Unit/AspectAttributes/MethodInvokeTestAttribute.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
namespace AspectCore.Test.Unit.AspectAttributes
77
{
8+
[AttributeUsage(AttributeTargets.Interface | AttributeTargets.Method)]
89
public class MethodInvokeTestAttribute: AspectAttribute
910
{
1011
public override void OnBefore(MethodExecutionArgs args)
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using System.Threading.Tasks;
2+
using AspectCore.Test.Unit.AspectAttributes;
3+
4+
namespace AspectCore.Test.Unit.Services
5+
{
6+
[MethodInvokeTest]
7+
public interface IInterfaceLevelAspectTestService
8+
{
9+
InvokeMethod TestAspectMethodInvoke(InvokeMethod invokeMethod);
10+
11+
Task<InvokeMethod> TestAspectMethodInvokeAsync(InvokeMethod invokeMethod);
12+
}
13+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace AspectCore.Test.Unit.Services
2+
{
3+
public class InheritenceAspectTestService: InterfaceLevelAspectTestService
4+
{
5+
6+
}
7+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
using System;
2+
using System.Threading.Tasks;
3+
4+
namespace AspectCore.Test.Unit.Services
5+
{
6+
public class InterfaceLevelAspectTestService: IInterfaceLevelAspectTestService
7+
{
8+
public InvokeMethod TestAspectMethodInvoke(InvokeMethod invokeMethod)
9+
{
10+
if (invokeMethod == InvokeMethod.OnException)
11+
throw new Exception("Test exception for OnException method invoke!");
12+
13+
return InvokeMethod.Nothing;
14+
}
15+
16+
public Task<InvokeMethod> TestAspectMethodInvokeAsync(InvokeMethod invokeMethod)
17+
{
18+
if (invokeMethod == InvokeMethod.OnExceptionAsync)
19+
throw new Exception("Test exception for OnExceptionAsync method invoke!");
20+
21+
return Task.FromResult(InvokeMethod.Nothing);
22+
}
23+
}
24+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
using System.Threading.Tasks;
2+
using AspectCore.Test.Unit.Services;
3+
using Microsoft.Extensions.DependencyInjection;
4+
using Xunit;
5+
6+
namespace AspectCore.Test.Unit.Tests
7+
{
8+
public class InterfaceLevelAspectAttributeTest
9+
{
10+
[Theory]
11+
[InlineData(InvokeMethod.OnBefore)]
12+
[InlineData(InvokeMethod.OnSuccess)]
13+
[InlineData(InvokeMethod.OnException)]
14+
[InlineData(InvokeMethod.OnAfter)]
15+
public void TestAspectMethodInvoke_ShouldBeExpectedResult_WithSpecificInvokeMethod(InvokeMethod invokedMethod)
16+
{
17+
// Arrange
18+
var services = new ServiceCollection()
19+
.AddTransient<IInterfaceLevelAspectTestService, InterfaceLevelAspectTestService>()
20+
.DecorateWithAspect<IInterfaceLevelAspectTestService>();
21+
22+
var provider = services.BuildServiceProvider();
23+
var testService = provider.GetRequiredService<IInterfaceLevelAspectTestService>();
24+
25+
// Actual
26+
InvokeMethod methodResult = testService.TestAspectMethodInvoke(invokedMethod);
27+
28+
// Assert
29+
Assert.Equal(invokedMethod, methodResult);
30+
}
31+
32+
[Theory]
33+
[InlineData(InvokeMethod.OnBeforeAsync)]
34+
[InlineData(InvokeMethod.OnSuccessAsync)]
35+
[InlineData(InvokeMethod.OnExceptionAsync)]
36+
[InlineData(InvokeMethod.OnAfterAsync)]
37+
public async Task TestAspectMethodInvokeAsync_ShouldBeExpectedResult_WithSpecificInvokeMethod(InvokeMethod invokedMethod)
38+
{
39+
// Arrange
40+
var services = new ServiceCollection()
41+
.AddTransient<IInterfaceLevelAspectTestService, InterfaceLevelAspectTestService>()
42+
.DecorateWithAspect<IInterfaceLevelAspectTestService>();
43+
44+
var provider = services.BuildServiceProvider();
45+
var testService = provider.GetRequiredService<IInterfaceLevelAspectTestService>();
46+
47+
// Actual
48+
InvokeMethod methodResult = await testService.TestAspectMethodInvokeAsync(invokedMethod);
49+
50+
// Assert
51+
Assert.Equal(invokedMethod, methodResult);
52+
}
53+
54+
[Theory]
55+
[InlineData(InvokeMethod.OnBeforeAsync)]
56+
[InlineData(InvokeMethod.OnSuccessAsync)]
57+
[InlineData(InvokeMethod.OnExceptionAsync)]
58+
[InlineData(InvokeMethod.OnAfterAsync)]
59+
public async Task TestAspectMethodInvokeAsync_ForInheritence_ShouldBeExpectedResult_WithSpecificInvokeMethod(InvokeMethod invokedMethod)
60+
{
61+
// Arrange
62+
var services = new ServiceCollection()
63+
.AddTransient<IInterfaceLevelAspectTestService, InheritenceAspectTestService>()
64+
.DecorateWithAspect<IInterfaceLevelAspectTestService>();
65+
66+
var provider = services.BuildServiceProvider();
67+
var testService = provider.GetRequiredService<IInterfaceLevelAspectTestService>();
68+
69+
// Actual
70+
InvokeMethod methodResult = await testService.TestAspectMethodInvokeAsync(invokedMethod);
71+
72+
// Assert
73+
Assert.Equal(invokedMethod, methodResult);
74+
}
75+
}
76+
}

0 commit comments

Comments
 (0)