/// <summary>
        /// Checks all Methods that returns Task or Task`1 if their naming is according to the convention.
        /// </summary>
        /// <param name="builder"></param>
        public void CheckAsyncMthodsNomenclature(Builder builder)
        {
            var task        = new __Task();
            var taskGeneric = new __Task_1();
            var methods     = builder
                              .GetTypes(SearchContext.Module)
                              .SelectMany(x => x.Methods)
                              .Where(x => (x.ReturnType == __Task.Type || x.ReturnType == __Task_1.Type) && !x.Name.EndsWith("Async") && !x.Name.EndsWith("Action"));

            foreach (var item in methods)
            {
                this.Log(LogTypes.Warning, item, $"The method '{item.Name}' in '{item.OriginType.Fullname}' is async, but does not have an 'Async' suffix.");
            }
        }
예제 #2
0
        private void ImplementTimedCache(Builder builder)
        {
            if (!builder.TypeExists(__TimedCacheAttribute.TypeName))
            {
                return;
            }

            var timedCacheAttribute = new __TimedCacheAttribute(builder);
            var methods             = builder.FindMethodsByAttribute(timedCacheAttribute.Type.Fullname);

            if (!methods.Any())
            {
                return;
            }

            var task   = new __Task(builder);
            var task_1 = new __Task_1(builder);

            foreach (var method in methods)
            {
                this.Log($"Implementing TimedCache in method {method.Method.Name}");

                if (method.Method.ReturnType.Fullname == "System.Void")
                {
                    this.Log(LogTypes.Warning, method.Method, "TimedCacheAttribute does not support void return types");
                    continue;
                }

                var keyName          = "<>timedcache_key";
                var timecacheVarName = "<>timedcache";

                if (method.AsyncMethod == null && method.Method.ReturnType.Inherits(task.Type.Fullname))
                {
                    this.Log(LogTypes.Error, method.Method, $"- TimedCacheAttribute for method {method.Method.Name} will not be implemented. Methods that returns 'Task' without async are not supported.");
                }
                else if (method.AsyncMethod == null)
                {
                    method.Method.NewCode()
                    .Context(x =>
                    {
                        var timedCache     = x.CreateVariable(timecacheVarName, method.Attribute.Type);
                        var key            = x.CreateVariable(keyName, timedCacheAttribute.CreateKey);
                        var returnVariable = x.GetReturnVariable();

                        x.Assign(timedCache).NewObj(method);

                        // Create a cache key
                        x.Call(timedCacheAttribute.CreateKey, method.Method.Fullname, x.GetParametersArray())
                        .StoreLocal(key);

                        // check
                        x.Load(timedCache).Call(timedCacheAttribute.HasCache, key)
                        .IsTrue().Then(y =>
                        {
                            y.Load(timedCache).Call(timedCacheAttribute.GetCache, key)
                            .As(method.Method.ReturnType)
                            .StoreLocal(returnVariable)
                            .Return();
                        });

                        x.OriginalBodyNewMethod().StoreLocal(returnVariable);

                        // Set the cache
                        x.Load(timedCache).Call(timedCacheAttribute.SetCache, key, returnVariable);

                        x.Load(returnVariable).Return();
                    })
                    .Replace();
                }
                else if (method.AsyncMethod != null)
                {
                    method.Method.NewCode()
                    .Context(x =>
                    {
                        var taskReturnType = method.Method.ReturnType.GetGenericArgument(0);
                        var timedCache     = x.CreateVariable(timecacheVarName, method.Attribute.Type);
                        var cacheKey       = x.CreateVariable(typeof(string));

                        x.Assign(cacheKey).Set(x.NewCode().Call(timedCacheAttribute.CreateKey, method.Method.Fullname, x.GetParametersArray()));
                        x.Assign(timedCache).NewObj(method);
                        x.Load(timedCache).Call(timedCacheAttribute.HasCache, cacheKey)
                        .IsTrue().Then(y =>
                        {
                            y.Call(task_1.FromResult.MakeGeneric(taskReturnType), y.NewCode().Call(timedCache, timedCacheAttribute.GetCache, cacheKey).As(taskReturnType))
                            .Return();
                        });
                    }).Insert(InsertionPosition.Beginning);

                    method.Method.NewCode()
                    .Context(x =>
                    {
                        var taskReturnType = method.Method.ReturnType.GetGenericArgument(0);
                        var returnVariable = x.GetReturnVariable();
                        x.LoadVariable(2).Call(timedCacheAttribute.SetCache, x.NewCode().LoadVariable(3), x.NewCode().Call(returnVariable, task_1.GetResult.MakeGeneric(taskReturnType)));
                    }).Insert(InsertionPosition.End);
                }

                method.Attribute.Remove();
            }
        }
예제 #3
0
        private void ImplementMethodCache(Builder builder)
        {
            var methods = builder.FindMethodsByAttribute("Cauldron.Interception.CacheAttribute");

            if (!methods.Any())
            {
                return;
            }

            var task   = new __Task(builder);
            var task_1 = new __Task_1(builder);

            foreach (var method in methods)
            {
                this.LogInfo($"Implementing Cache for method {method.Method.Name}");

                if (method.Method.ReturnType.Fullname == "System.Void")
                {
                    this.LogWarning("CacheAttribute does not support void return types");
                    continue;
                }

                var cacheField = $"<{method.Method.Name}>m__MethodCache_{method.Identification}";

                if (method.AsyncMethod == null && method.Method.ReturnType.Inherits(task.Type.Fullname))
                {
                    this.LogWarning($"- CacheAttribute for method {method.Method.Name} will not be implemented. Methods that returns 'Task' without async are not supported.");
                }
                else if (method.AsyncMethod == null)
                {
                    method.Method.NewCode()
                    .Context(x =>
                    {
                        var cache          = method.Method.DeclaringType.CreateField(method.Method.Modifiers.GetPrivate(), method.Method.ReturnType, cacheField);
                        var returnVariable = x.GetReturnVariable();

                        x.Load(cache).IsNull().Then(y =>
                        {
                            y.OriginalBody().StoreLocal(returnVariable).Return();
                        })
                        .Load(cache).Return();
                    })
                    .Replace();
                }
                else if (method.AsyncMethod != null)
                {
                    method.Method.NewCode()
                    .Context(x =>
                    {
                        var taskReturnType = method.Method.ReturnType.GetGenericArgument(0);
                        var cache          = method.Method.DeclaringType.CreateField(method.Method.Modifiers.GetPrivate(), taskReturnType, cacheField);

                        x.Load(cache).IsNotNull().Then(y =>
                        {
                            y.Call(task_1.FromResult.MakeGeneric(taskReturnType), cache).Return();
                        });
                    }).Insert(InsertionPosition.Beginning);

                    method.Method.NewCode()
                    .Context(x =>
                    {
                        var taskReturnType = method.Method.ReturnType.GetGenericArgument(0);
                        var cache          = method.Method.DeclaringType.GetField(cacheField);
                        var returnVariable = x.GetReturnVariable();
                        x.Assign(cache).Set(x.NewCode().Call(returnVariable, task_1.GetResult.MakeGeneric(taskReturnType)));
                    }).Insert(InsertionPosition.End);
                }

                method.Attribute.Remove();
            }
        }