问题点:
一般情况下,是无法把Type类型当做泛型T来使用的,你会收到IDE的提示如下
这里当然可以直接将Person传入泛型,但我使用一个Person类来获取Type只是为了测试,
因为有一些情况下我们只有运行中的Type对象,并不知道它具体叫什么。
并要使用其作为方法的泛型
按IDE的提示,我们无法这样直接使用,
但是微软为我们提供了反射的方法实现这一功能
解决方法
使用
public class Tests
{
public static string TestMethod<T>()
{
Console.WriteLine("具体的传入类型为"+typeof(T));
return "这是个测试";
}
internal class Person
{
public string Name { get; set; }
public int Id { get; set; }
}
[Test]
public void Test1()
{
Type targetType = typeof(Person);
//无法直接使用
Tests.TestMethod<targetType>();
//可以使用,MakeGenericMethod可以获取多个一个及多个泛型
MethodInfo method = typeof(Tests).GetMethod("TestMethod").MakeGenericMethod(targetType);
Console.WriteLine(method.Invoke(null, null));
}
[SetUp]
public void Setup()
{
}
}
}
解决的实际问题:
我有一个ASP.NET CORE的缓存工具,
在gitee上可以查看https://gitee.com/godenSpirit/cache-attribute
使用的是SqlSugar提供的Redis帮助类来实现下面的接口
public interface ICacheable
{
/// <summary>
/// 泛型获取
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <returns></returns>
T Get<T>(string key);
/// <summary>
/// object获取
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
object Get(string key);
...........
}
其中使用非泛型缓存方法时会得到别多包装一层的object缓存,无法在正确返回到Swagger
故改用泛型方法,
具体代码如下,
//[CacheAble策略]的方法执行前,第一个策略每一行都注释一下,如果回头看只需参考这个即可
CacheAble_Strategy_Before = (context, _cache) => {
//获取调用接口的Controller
ControllerActionDescriptor controller = (ControllerActionDescriptor)context.ActionDescriptor;
//进一步获取调用的接口的反射对象
MethodInfo method = controller.MethodInfo;
//从反射上拿到策略对应的Attribute,
CacheAbleAttribute attribute = (CacheAbleAttribute)method.GetCustomAttribute(typeof(CacheAbleAttribute));
//获取Attribute中需要解析的缓存名属性TotalName,解析ToTalName,替换得出真正的缓存名
string real_cacheName = CacheNameResolver.ResolveTotalName(attribute.Totoal_Name, context);
//如果注解的参数为空则直接报异常
if (string.IsNullOrEmpty(attribute.preffix) || string.IsNullOrEmpty(attribute.Totoal_Name))
throw new CacheAbleArgsException("The Args Cannot Be NULL");
//拿到解析的缓存名去缓存里找是否有该缓存
if (_cache.Exist(attribute.preffix + real_cacheName)&&attribute.work==true)
{
//StandResult<object> res = _cache.Get<StandResult<object>>(attribute.preffix + real_cacheName); 测试用的标志返回类型,可以正确获取
//获取返回值的类型
Type returnType = method.ReturnType;
//获取泛型Get方法的反射(通过返回值的Type指定方法泛型)
MethodInfo GetGen = _cache.GetType().GetMethod("Get").MakeGenericMethod(returnType);
//放射调用泛型Get方法,获取正确的缓存信息
object res = GetGen.Invoke(_cache,new object[] {attribute.preffix+real_cacheName});
return res;
}
else
{
return null; //没找到就返回Null
}
};
详情可以查看我的这个CacheAttribute工具的源码,欢迎提出意见。