如何通过返回值作为参数传递动态方法?

时间:2017-11-28 06:46:52

标签: c# dynamic delegates

我有很多方法,我需要将其中一些放入缓存中。但是我不希望它编辑每种方法。

如何将返回值作为参数传递给动态方法?请在我的代码中将评论作为我的一些问题进行检查。

感谢您提前。

private string GetUserName(string userId)
        {
            // how can I pass the method as parameter? 
            // Method is dynamic and can be any method with parameter(s) and return value
            return CacheIt<string>(item => GetUserNameFromDb(userId)); 
        }

        private T CacheIt<T>(Action<T> action) // Im not sure if this an Action
        {
            var key = "UserInfo." + userId; // how can I get the value of the parameter?

            var cache = MemoryCache.Default;
            var value = (T) cache[key];

            if (value != null)
                return value;

            value = action(); // how can I call the action or the method

            var policy = new CacheItemPolicy { SlidingExpiration = new TimeSpan(1, 0, 0) };
            cache.Add(key, value, policy);

            return value;

        }

        private string GetUserNameFromDb(string userId)
        {
            return "FirstName LastName";
        }

2 个答案:

答案 0 :(得分:1)

像这样修改CacheIt方法;输入参数作为对象类型传递给方法,对于创建缓存键,输入对象被序列化为Json,json结果计算为MD5。 MD5结果作为存储在缓存中。此外,操作不会返回值,我使用 Func 而不是操作。我们期望为缓存返回值。

    private T2 CacheIt<T2>(Func<T2> func, object input)
    {
        var key = CreateMD5(JsonConvert.SerializeObject(input));
        var cache = MemoryCache.Default;
        var value = cache.Get(key);
        if (value != null)
        {
            return (T2)value;
        }
        value = func();
        var policy = new CacheItemPolicy { SlidingExpiration = new TimeSpan(1, 0, 0) };
        cache.Add(key, value, policy);
        return (T2)value;
    }

    private string CreateMD5(string input)
    {
        using (System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create())
        {
            byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(input);
            byte[] hashBytes = md5.ComputeHash(inputBytes);
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < hashBytes.Length; i++)
            {
                sb.Append(hashBytes[i].ToString("X2"));
            }
            return sb.ToString();
        }
    }

最后,GetUserName和GetUserNameFromDb方法看起来像这样;

    private string GetUserName(string userId,string anotherParameter)
    {
        return CacheIt<string>(() => GetUserNameFromDb(userId, anotherParameter), new { userId,anotherParameter });
    }

    private string GetUserNameFromDb(string userId, string anotherParameter)
    {
        return "FirstName LastName";
    }

<强>用法;

GetUserName("1","AnotherParameter");
  

注意:也许可能有更好的方法来获取输入参数   直接来自func方法中的CacheIt

答案 1 :(得分:0)

我们可以通过

动态传递方法而不管方法定义
 public T CacheIt<T>(object container,string methodName,params object[] parameterlist)
    {
        MethodInfo func = container.GetType().GetMethod(methodName);
        var cache = MemoryCache.Default;
        T value = (T)cache.Get(func.Name);
        if(value!=null)
        {
            return value;
        }
        value = (T)func.Invoke(container,parameterlist);

        cache.Add(func.Name, value,new CacheItemPolicy());
        return value;

    }

    public void PrintUserName()
    {
     CacheIt<string>(this,nameof(this.GetUserName),"1");
        CacheIt<string>(this, nameof(this.GetFullName), "Raghu","Ram");
        Console.Read();
    }

    public string GetUserName(string userId)
    {
        // how can I pass the method as parameter? 
        // Method is dynamic and can be any method with parameter(s) and return value
        //return CacheIt<string>(item => GetUserNameFromDb(userId));
        return $"UserId : {userId} & UserName:Vaishali";
    }

    public string GetFullName(string FirstName,string  LastName)
    {
        return $"FullName : {string.Concat(FirstName," ",LastName)}";
    }

使用'out'和'ref'变量可以正常工作,但是获取out和ref变量的值并不容易,为此我们必须对ParameterInfo的东西做更多的工作。