Skip to content

Commit

Permalink
Update method visibility, add support for custom function keys, updat…
Browse files Browse the repository at this point in the history
…e example project
  • Loading branch information
gregyjames committed Nov 28, 2024
1 parent 8b73566 commit 96bb48e
Show file tree
Hide file tree
Showing 7 changed files with 47 additions and 44 deletions.
4 changes: 1 addition & 3 deletions gj.autofac.caching.redis.tester/ExampleService.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using System.Threading.Tasks;
using gj.autofac.caching.redis;
using RedisCacheTester;
namespace gj.autofac.caching.redis.tester;

public class ExampleService : IExampleService
{
Expand Down
12 changes: 4 additions & 8 deletions gj.autofac.caching.redis.tester/IExampleService.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
using gj.autofac.caching.redis;

namespace RedisCacheTester;

using System.Threading.Tasks;
namespace gj.autofac.caching.redis.tester;

public interface IExampleService
{
[RedisCache(60)]
[RedisCache(120)]
Task<int[]> AsyncFunctionTest(int id);

[RedisCache(60)]
[RedisCache(120)]
Task AsyncActionTest(int id);
[RedisCache(60)]
[RedisCache(120)]
int SynchronousTaskTest();
}
8 changes: 5 additions & 3 deletions gj.autofac.caching.redis.tester/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
using Autofac;
using Autofac.Extensions.DependencyInjection;
using Autofac.Extras.DynamicProxy;
using gj.autofac.caching.redis;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using RedisCacheTester;
using Serilog;
using Serilog.Events;

namespace gj.autofac.caching.redis.tester;

static class Program
{
static void TimeAndRun(Action action)
Expand All @@ -18,7 +18,7 @@ static void TimeAndRun(Action action)
start.Stop();
Console.WriteLine(start.Elapsed.TotalMilliseconds);
}
static async Task Main()
static Task Main()
{
RedisConnectionManager.Host = "192.168.0.47";
RedisConnectionManager.Port = 6379;
Expand Down Expand Up @@ -63,5 +63,7 @@ static async Task Main()
{
TimeAndRun(() => service.SynchronousTaskTest());
}

return Task.CompletedTask;
}
}
6 changes: 3 additions & 3 deletions gj.autofac.caching.redis/BinaryFormatterUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@

namespace gj.autofac.caching.redis;

public static class BinaryFormatterUtils
internal static class BinaryFormatterUtils
{
/// <summary>
/// Serializes an object to binary using MessagePack.
/// </summary>
/// <param name="obj">The object to serialize.</param>
/// <returns>The binary representation of the object.</returns>
public static byte[] SerializeToBinary(object obj)
internal static byte[] SerializeToBinary(object? obj)
{
if (obj == null)
{
Expand All @@ -26,7 +26,7 @@ public static byte[] SerializeToBinary(object obj)
/// <param name="binaryData">The binary data to deserialize.</param>
/// <param name="type">The type to deserialize into.</param>
/// <returns>The deserialized object.</returns>
public static object DeserializeFromBinary(byte[] binaryData, Type type)
internal static object? DeserializeFromBinary(byte[] binaryData, Type type)
{
if (binaryData == null || binaryData.Length == 0)
{
Expand Down
8 changes: 8 additions & 0 deletions gj.autofac.caching.redis/MethodType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace gj.autofac.caching.redis;

internal enum MethodType
{
Synchronous,
AsyncAction,
AsyncFunction
}
3 changes: 2 additions & 1 deletion gj.autofac.caching.redis/RedisCacheAttribute.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
namespace gj.autofac.caching.redis;

[AttributeUsage(AttributeTargets.Method)]
public class RedisCacheAttribute(int durationSeconds = 60) : Attribute
public class RedisCacheAttribute(int durationSeconds = 60, string key = "") : Attribute
{
public int DurationSeconds { get; } = durationSeconds;
public string Key { get; set; } = key;
}
50 changes: 24 additions & 26 deletions gj.autofac.caching.redis/RedisCacheInterceptor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ public class RedisCacheInterceptor(ILogger<RedisCacheInterceptor> logger) : IInt

private static string GenerateCacheKey(MethodInfo method, object[] args)
{
var argsKey = string.Join(",", args.Select(a => a?.ToString() ?? "null"));
return $"{method.DeclaringType.FullName}.{method.Name}({argsKey})";
var argsKey = string.Join(",", args.Select(a => a.ToString() ?? "null"));
return $"{method.DeclaringType?.FullName}.{method.Name}({argsKey})";
}

private Type GetReturnType(IInvocation invocation)
Expand Down Expand Up @@ -40,20 +40,14 @@ private MethodType GetDelegateType(IInvocation invocation)
return MethodType.Synchronous;
}

private enum MethodType
{
Synchronous,
AsyncAction,
AsyncFunction
}

private static readonly MethodInfo HandleAsyncMethodInfo = typeof(RedisCacheInterceptor).GetMethod("HandleAsyncWithResult", BindingFlags.Instance | BindingFlags.NonPublic);
private static readonly MethodInfo? HandleAsyncMethodInfo = typeof(RedisCacheInterceptor).GetMethod("HandleAsyncWithResult", BindingFlags.Instance | BindingFlags.NonPublic);

private async Task HandleAsync(Task task)
{
await task;
}

// ReSharper disable once UnusedMember.Local
private async Task<T> HandleAsyncWithResult<T>(Task<T> task)
{
return await task;
Expand All @@ -71,7 +65,7 @@ public void Intercept(IInvocation invocation)
return;
}

var cacheKey = GenerateCacheKey(invocation.Method, invocation.Arguments);
var cacheKey = string.IsNullOrEmpty(cacheAttribute.Key) ? GenerateCacheKey(invocation.Method, invocation.Arguments) : cacheAttribute.Key;
var cachedValue = _redis.StringGet(cacheKey);

if (cachedValue.HasValue)
Expand Down Expand Up @@ -105,7 +99,7 @@ public void Intercept(IInvocation invocation)
private static void SetReturnValue(IInvocation invocation, RedisValue cachedValue, Type returnType)
{
// Deserialize using the provided returnType
var value = BinaryFormatterUtils.DeserializeFromBinary(cachedValue, returnType);
var value = BinaryFormatterUtils.DeserializeFromBinary(cachedValue!, returnType);

if (typeof(Task).IsAssignableFrom(invocation.Method.ReturnType))
{
Expand Down Expand Up @@ -139,20 +133,24 @@ private void HandleSyncMethod(IInvocation invocation, string cacheKey, int expir
invocation.Proceed();

var resultType = invocation.Method.ReturnType.GetGenericArguments()[0];
var mi = HandleAsyncMethodInfo.MakeGenericMethod(resultType);
var value = mi.Invoke(this, new[] { invocation.ReturnValue });

var task = (Task)value;
await task.ConfigureAwait(false);

var resultProperty = task.GetType().GetProperty("Result");
var taskValue = resultProperty?.GetValue(task);

var serializedValue = BinaryFormatterUtils.SerializeToBinary(taskValue);
await _redis.StringSetAsync(cacheKey, serializedValue, TimeSpan.FromSeconds(expirationSeconds));

logger.LogDebug("[CACHE SET] {0}", cacheKey);
invocation.ReturnValue = value;
var mi = HandleAsyncMethodInfo?.MakeGenericMethod(resultType);
var value = mi?.Invoke(this, new[] { invocation.ReturnValue });

if (value != null)
{
var task = (Task)value;

await task.ConfigureAwait(false);

var resultProperty = task.GetType().GetProperty("Result");
var taskValue = resultProperty?.GetValue(task);

var serializedValue = BinaryFormatterUtils.SerializeToBinary(taskValue);
await _redis.StringSetAsync(cacheKey, serializedValue, TimeSpan.FromSeconds(expirationSeconds));

logger.LogDebug("[CACHE SET] {0}", cacheKey);
invocation.ReturnValue = value;
}

return value;
}
Expand Down

0 comments on commit 96bb48e

Please sign in to comment.