I am trying to write a simple caching mechanism. Basically, whenever a method is called, its return value should be saved in a cache. Using AOP, my simplified CacheAspect looks as follows.
using Castle.DynamicProxy;
public class CacheAspect : IInterceptor
{
private object cache;
public void Intercept(IInvocation invocation)
{
if (cache is null)
{
invocation.Proceed();
cache = invocation.ReturnValue;
return;
}
invocation.ReturnValue = cache;
}
}
However, when the aspect intercepts a method that uses yield return, it only caches the compiler-generated state machine and not the materialized result. Therefore, I would like the aspect to fail-fast in that case.
Therefore I want to deduct from a method's return value, whether or not it uses yield return. So far, I have only found this solution that gets the job done.
private static bool IsReturnTypeCompilerGenerated(IInvocation invocation) =>
invocation
.ReturnValue
.GetType()
.GetCustomAttribute(typeof(CompilerGeneratedAttribute), inherit: true)
is object;
My issue with this is that I don't know, what other compiler-generated types there are and in which situations they arise. Is it possible, that I exclude methods from my caching mechanism that shouldn't be excluded? Or put differently: Is there a way to more specifically target methods that use yield return?