using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.Serialization;
using System.Text;
using NewLife.Collections;
using NewLife.Log;
namespace NewLife.Reflection
{
/// <summary>类型辅助类</summary>
public class TypeX : MemberInfoX
{
#region 属性
private Type _Type;
/// <summary>类型</summary>
public override Type Type { get { return _Type; } }
FastHandler _Handler;
/// <summary>快速调用委托,延迟到首次使用才创建</summary>
FastHandler Handler
{
get
{
if (_Handler == null)
{
if (Type.IsValueType || Type.IsArray)
_Handler = GetConstructorInvoker(Type, null);
else
{
var cs = Type.GetConstructors(DefaultBinding);
if (cs != null && cs.Length > 0) _Handler = GetConstructorInvoker(Type, cs[0]);
}
}
return _Handler;
}
}
#endregion
#region 名称
private String _Name;
/// <summary>类型名称。主要处理泛型</summary>
public override String Name { get { return _Name ?? (_Name = GetName(_Type, false)); } }
private String _FullName;
/// <summary>完整类型名称。包含命名空间,但是不包含程序集信息</summary>
public String FullName { get { return _FullName ?? (_FullName = GetName(_Type, true)); } }
/// <summary>获取类型的友好名称</summary>
/// <param name="type">指定类型</param>
/// <param name="isfull">是否全名,包含命名空间</param>
/// <returns></returns>
[EditorBrowsable(EditorBrowsableState.Advanced)]
public static String GetName(Type type, Boolean isfull = false)
{
if (type.IsNested) return GetName(type.DeclaringType, isfull) + "." + type.Name;
if (!type.IsGenericType) return isfull ? type.FullName : type.Name;
var sb = new StringBuilder();
var typeDef = type.GetGenericTypeDefinition();
var name = isfull ? typeDef.FullName : typeDef.Name;
var p = name.IndexOf("`");
if (p >= 0)
sb.Append(name.Substring(0, p));
else
sb.Append(name);
sb.Append("<");
var ts = type.GetGenericArguments();
for (int i = 0; i < ts.Length; i++)
{
if (i > 0) sb.Append(",");
if (!ts[i].IsGenericParameter) sb.Append(GetName(ts[i], isfull));
}
sb.Append(">");
return sb.ToString();
}
#endregion
#region 构造
private TypeX(Type type) : base(type) { _Type = type; }
private static DictionaryCache<Type, TypeX> cache = new DictionaryCache<Type, TypeX>();
/// <summary>创建类型辅助对象</summary>
/// <param name="type">类型</param>
/// <returns></returns>
public static TypeX Create(Type type)
{
if (type == null) throw new ArgumentNullException("type");
return cache.GetItem(type, key => new TypeX(key));
}
#endregion
#region 创建动态方法
delegate Object FastHandler(Object[] parameters);
private static FastHandler GetConstructorInvoker(Type target, ConstructorInfo constructor)
{
// 定义一个没有名字的动态方法。
// 关联到模块,并且跳过JIT可见性检查,可以访问所有类型的所有成员
var dynamicMethod = new DynamicMethod(String.Empty, typeof(Object), new Type[] { typeof(Object[]) }, target.Module, true);
{
var il = dynamicMethod.GetILGenerator();
if (target.IsValueType)
il.NewValueType(target).BoxIfValueType(target).Ret();
else if (target.IsArray)
il.PushParams(0, new Type[] { typeof(Int32) }).NewArray(target.GetElementType()).Ret();
else
il.PushParams(0, constructor).NewObj(constructor).Ret();
}
#if DEBUG
//SaveIL(dynamicMethod, delegate(ILGenerator il)
// {
// EmitHelper help = new EmitHelper(il);
// if (target.IsValueType)
// help.NewValueType(target).BoxIfValueType(target).Ret();
// else if (target.IsArray)
// help.PushParams(0, new Type[] { typeof(Int32) }).NewArray(target.GetElementType()).Ret();
// else
// help.PushParams(0, constructor).NewObj(constructor).Ret();
// });
#endif
return (FastHandler)dynamicMethod.CreateDelegate(typeof(FastHandler));
}
#endregion
#region 调用
/// <summary>创建实例</summary>
/// <param name="parameters">参数数组</param>
/// <returns></returns>
[DebuggerStepThrough]
public override Object CreateInstance(params Object[] parameters)
{
if (Type.ContainsGenericParameters || Type.IsGenericTypeDefinition)
throw new XException(Type.FullName + "类是泛型定义类,缺少泛型参数!");
if (Type.IsValueType) return Handler.Invoke(parameters);
// 数组的动态构造参数是元素个数,如果未指定,应该默认0
if (Type.IsArray)
{
if (parameters == null || parameters.Length < 1) parameters = new Object[] { 0 };
return Handler.Invoke(parameters);
}
//// 无参数,直接构造
//if (parameters == null || parameters.Length < 1) return Handler.Invoke(new Object[0]);
// 准备参数类型数组,以匹配构造函数
//var paramTypes = Type.EmptyTypes;
//if (parameters != null && parameters.Length > 0)
//{
// var list = new List<Type>();
// foreach (var item in parameters)
// {
// if (item != null)
// list.Add(item.GetType());
// else
// list.Add(typeof(Object));
// }
// paramTypes = list.ToArray();
//}
var paramTypes = TypeX.GetTypeArray(parameters);
var ctor = GetConstructor(paramTypes);
var handler = GetHandler(ctor);
if (handler != null) return handler.Invoke(parameters);
if (paramTypes != Type.EmptyTypes)
{
paramTypes = Type.EmptyTypes;
ctor = GetConstructor(paramTypes);
handler = GetHandler(ctor);
if (handler != null)
{
// 更换了构造函数,要重新构造构造函数的参数
var ps = ctor.GetParameters();
parameters = new Object[ps.Length];
for (int i = 0; i < ps.Length; i++)
{
// 处理值类型
if (ps[i].ParameterType.IsValueType)
parameters[i] = TypeX.CreateInstance(ps[i].ParameterType);
else
parameters[i] = null;
}
// 如果这里创建失败,后面还可以创建一个未初始化
try
{
return handler.Invoke(parameters);
}
catch { }
}
}
// 如果没有找到构造函数,则创建一个未初始化的对象
return FormatterServices.GetSafeUninitializedObject(Type);
}
DictionaryCache<ConstructorInfo, FastHandler> _cache = new DictionaryCache<ConstructorInfo, FastHandler>();
FastHandler GetHandler(ConstructorInfo constructor)
{
if (constructor == null) return null;
return _cache.GetItem(constructor, key => GetConstructorInvoker(Type, key));
}
ConstructorInfo GetConstructor(Type[] paramTypes)
{
var bf = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
// 1,如果参数为null,则找第一个参数
// 2,根据参数找一次,如果参数为空,也许能找到无参构造函数
// 3,如果还没找到,参数又为空,采用第一个构造函数。这里之所以没有和第一步合并,主要是可能调用者只想要无参构造函数,而第一个不是
ConstructorInfo constructor = null;
if (paramTypes == null)
{
constructor = Type.GetConstructors(bf).FirstOrDefault();
paramTypes = Type.EmptyTypes;
}
if (constructor == null) constructor = Type.GetConstructor(bf, null, paramTypes, null);
//if (constructor == null) throw new Exception("没有找到匹配的构造函数!");
if (constructor == null && paramTypes == Type.EmptyTypes) constructor = Type.GetConstructors(bf).FirstOrDefault();
return constructor;
}
/// <summary>快速反射创建指定类型的实例</summary>
/// <param name="type">类型</param>
/// <param name="parameters">参数数组</param>
/// <returns></returns>
public static Object CreateInstance(Type type, params Object[] parameters)
{
if (type == null) throw new ArgumentNullException("type");
return Create(type).CreateInstance(parameters);
}
/// <summary>快速反射创建指定类型的实例</summary>
/// <typeparam name="T"></typeparam>
/// <param name="parameters">参数数组</param>
/// <returns></returns>
public static Object CreateInstance<T>(params Object[] parameters)
{
return Create(typeof(T)).CreateInstance(parameters);
}
/// <summary>取值,返回自己</summary>
/// <param name="obj"></param>
/// <returns></returns>
public override Object GetValue(Object obj)
{
return obj;
}
#endregion
#region 扩展属性
/// <summary>是否系统类型</summary>
/// <returns></returns>
public Boolean IsSystemType
{
get
{
return Type.Assembly.FullName.EndsWith("PublicKeyToken=b77a5c561934e089");
}
}
#endregion
#region 方法
/// <summary>是否指定类型的插件</summary>
/// <param name="baseType">指定类型</param>
/// <returns></returns>
public Boolean IsPlugin(Type baseType)
{
//if (type == null) throw new ArgumentNullException("type");
// 如果基类为空,则表示是插件
if (baseType == null) return true;
// 是否严格匹配。严格匹配仅比较对象引用,否则比较名称
// 对于只反射类型来说,不需要严格,因为它们不会是同一个引用,一般用于判断是插件意见才加载
// 对于普通类型,很有可能一个程序集被加载多次,必须严格匹配所引用的就是那个接口类型,否则类型无法转换
var strict = !Type.Assembly.ReflectionOnly;
//为空、不是类、抽象类、泛型类 都不是实体类
//if (!BaseType.IsClass || BaseType.IsAbstract || BaseType.IsGenericType) return false;
// 允许值类型,仅排除接口
if (Type.IsInterface || Type.IsAbstract || Type.IsGenericType) return false;
if (baseType.IsInterface)
{
var ts = Type.GetInterfaces();
if (ts == null || ts.Length < 1) return false;
if (strict)
return Array.IndexOf(ts, baseType) >= 0;
else
return ts.Any(e => e == baseType || e.FullName == baseType.FullName && e.AssemblyQualifiedName == baseType.AssemblyQualifiedName);
}
else
{
if (baseType.IsAssignableFrom(Type)) return true;
var e = Type;
while (e != null && e != typeof(Object))
{
if (strict)
{
if (e == baseType) return true;
}
else
{
if (e.FullName == baseType.FullName && e.AssemblyQualifiedName == baseType.AssemblyQualifiedName) return true;
}
e = e.BaseType;
}
return false;
}
}
/// <summary>根据名称获取类型</summary>
/// <param name="typeName">类型名</param>
/// <returns></returns>
public static Type GetType(String typeName)
{
return GetType(typeName, false);
}
static DictionaryCache<String, Type> typeCache = new DictionaryCache<String, Type>() { CacheDefault = false };
/// <summary>根据名称获取类型</summary>
/// <param name="typeName">类型名</param>
/// <param name="isLoadAssembly">是否从未加载程序集中获取类型。使用仅反射的方法检查目标类型,如果存在,则进行常规加载</param>
/// <returns></returns>
public static Type GetType(String typeName, Boolean isLoadAssembly)
{
if (String.IsNullOrEmpty(typeName)) throw new ArgumentNullException("typeName");
//String key = (isLoadAssembly ? "1" : "0") + typeName;
// isLoadAssembly不参与缓存的键,对于缓存来说,只要能找到类型就行,不必关心是否外部程序集
return typeCache.GetItem<Boolean>(typeName, isLoadAssembly, GetTypeInternal);
}
private static Type GetTypeInternal(String typeName, Boolean isLoadAssembly)
{
// 基本获取
var type = Type.GetType(typeName);
if (type != null) return type;
// 处理泛型
if (typeName[typeName.Length - 1] == '>') return GetGenericType(typeName, isLoadAssembly);
// 处理数组 有可能是 aa [[ dddd ]] ,也有可能是 aa[dddd]
if (typeName[typeName.Length - 1] == ']') return GetArrayType(typeName, isLoadAssembly);
// 处理内嵌类型
// 尝试本程序集
var asms = new[] {
AssemblyX.Create(Assembly.GetExecutingAssembly()),
AssemblyX.Create(Assembly.GetCallingAssembly()),
AssemblyX.Create(Assembly.GetEntryAssembly()) };
var loads = new List<AssemblyX>();
foreach (var asm in asms)
{
if (asm == null || loads.Contains(asm)) continue;
loads.Add(asm);
type = asm.GetType(typeName);
if (type != null) return type;
}
// 尝试所有程序集
foreach (var asm in AssemblyX.GetAssemblies())
{
if (loads.Contains(asm)) continue;
loads.Add(asm);
type = asm.GetType(typeName);
if (type != null) return type;
}
// 尝试加载只读程序集
if (isLoadAssembly)
{
foreach (var asm in AssemblyX.ReflectionOnlyGetAssemblies())
{
type = asm.GetType(typeName);
if (type != null)
{
// 真实加载
//var file = asm.Asm.CodeBase;
//if (String.IsNullOrEmpty(file))
// file = asm.Asm.Location;
//else if (file.StartsWith("file:///"))
// file = file.Substring("file:///".Length);
// ASP.Net中不会锁定原始DLL文件
var file = asm.Asm.Location;
try
{
type = null;
var asm2 = Assembly.LoadFile(file);
var type2 = AssemblyX.Create(asm2).GetType(typeName);
if (type2 == null) continue;
type = type2;
if (XTrace.Debug) XTrace.WriteLine("TypeX.GetType(\"{0}\")导致加载{1}", typeName, file);
}
catch (Exception ex)
{
if (XTrace.Debug) XTrace.WriteException(ex);
}
return type;
}
}
}
return null;
}
private static Type GetGenericType(String typeName, Boolean isLoadAssembly)
{
var start = typeName.IndexOf("<");
if (start <= 0) return null;
var end = typeName.LastIndexOf(">");
// <>也不行
if (end <= start + 1 || end != typeName.Length - 1) return null;
// GT<P1,P2,P3,P4>
var gname = typeName.Substring(0, start);
var pname = typeName.Substring(start + 1, end - start - 1);
//pname = "P1,P2<aa,bb>,P3,P4";
var pnames = new List<String>();
// 因为泛型参数里面还可能含有泛型,只能用栈来分析泛型参数了
var count = 0;
var last = 0;
for (var i = 0; i < pname.Length; i++)
{
var item = pname[i];
if (item == '<')
count++;
else if (item == '>')
count--;
else if (item == ',' && count == 0)
{
pnames.Add(pname.Substring(last, i - last).Trim());
last = i + 1;
}
}
if (last <= pname.Length) pnames.Add(pname.Substring(last, pname.Length - last).Trim());
// 泛型定义名称等于泛型类名加上参数数量
gname += "`" + pnames.Count;
// 先找外部的,如果外部都找不到,那就没意义了
var gt = GetType(gname, isLoadAssembly);
if (gt == null) return null;
var ts = new List<Type>(pnames.Count);
foreach (var item in pnames)
{
// 如果任何一个参数为空,说明这只是一个泛型定义而已
if (String.IsNullOrEmpty(item)) return gt;
var t = GetType(item, isLoadAssembly);
if (t == null) return null;
ts.Add(t);
}
return gt.MakeGenericType(ts.ToArray());
}
private static Type GetArrayType(String typeName, Boolean isLoadAssembly)
{
// 处理数组 有可能是 aa [[ dddd ]] ,也有可能是 aa[dddd]
// 因Json.cs 序列化Dictionary或泛型数组 导致报错,追踪至此作了调整,只是优化了算法,应该不会产生后果 (上海石头 2013.4.8)
bool blnFlag = false;
var start = typeName.LastIndexOf("[[");
if (start > 0) blnFlag = true;
if (start < 0) start = typeName.LastIndexOf("[");
if (start > 0) return null;
Int32 end = typeName.LastIndexOf("]]");
if (end < 0) end = typeName.LastIndexOf("]");
if (end > start) return null;
// Int32[][] String[,,]
var gname = typeName.Substring(0, start);
var pname = "";
if (blnFlag == false)
pname = typeName.Substring(start + 1, end - start - 1);
else
pname = typeName.Substring(start + 2, end - start - 2);
// 先找外部的,如果外部都找不到,那就没意义了
var gt = GetType(gname, isLoadAssembly);
if (gt == null) return null;
if (String.IsNullOrEmpty(pname)) return gt.MakeArrayType();
//pname = ",,,";
var pnames = pname.Split(new Char[] { ',' });
if (pnames == null || pnames.Length < 1) return gt.MakeArrayType();
if (gt.IsGenericType == true) //如果是泛型对象
{
//Type[] tmpType = { Type.GetType(pnames[0]) };
//return gt.MakeGenericType(tmpType);
return gt.MakeGenericType(pnames.Select(n => GetType(n, isLoadAssembly)).ToArray());
}
else
return gt.MakeArrayType(pnames.Length);
}
#endregion
#region 获取方法
/// <summary>获取方法。</summary>
/// <remarks>用于具有多个签名的同名方法的场合,不确定是否存在性能问题,不建议普通场合使用</remarks>
/// <param name="type">类型</param>
/// <param name="name">名称</param>
/// <param name="paramTypes"></param>
/// <returns></returns>
public static MethodInfo GetMethod(Type type, String name, Type[] paramTypes)
{
var bf = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance;
if (paramTypes == null) paramTypes = Type.EmptyTypes;
MethodInfo mi = null;
// 如果没有传入参数类型,则考虑返回第一个符合的
if (paramTypes.Length <= 0)
{
var t = type;
while (t != null && t != typeof(Object))
{
var mis = t.GetMethods(bf).Where(m => m.Name == name);
if (mis != null)
{
foreach (var item in mis)
{
// 碰巧找到也是无参的方法
if (item.GetParameters().Length == 0) return item;
// 记录第一个
if (mi == null) mi = item;
}
}
t = t.BaseType;
}
}
{
var t = type;
while (t != null && t != typeof(Object))
{
var m = t.GetMethod(name, bf, Binder, paramTypes, null);
if (m != null) return m;
t = t.BaseType;
}
}
// 如果没有找到匹配项,返回第一个
return mi;
}
/// <summary>获取方法。</summary>
/// <remarks>用于具有多个签名的同名方法的场合,不确定是否存在性能问题,不建议普通场合使用</remarks>
/// <param name="name">名称</param>
/// <param name="paramTypes"></param>
/// <returns></returns>
public MethodInfoX GetMethod(String name, Type[] paramTypes) { return GetMethod(Type, name, paramTypes); }
private static Binder _Binder;
/// <summary>专用绑定器</summary>
private static Binder Binder { get { return _Binder ?? (_Binder = new MyBinder()); } }
class MyBinder : Binder
{
public override FieldInfo BindToField(BindingFlags bindingAttr, FieldInfo[] match, object value, CultureInfo culture)
{
throw new NotImplementedException();
}
public override MethodBase BindToMethod(BindingFlags bindingAttr, MethodBase[] match, ref object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] names, out object state)
{
throw new NotImplementedException();
}
public override object ChangeType(object value, Type type, CultureInfo culture)
{
throw new NotImplementedException();
}
public override void ReorderArgumentArray(ref object[] args, object state)
{
throw new NotImplementedException();
}
public override MethodBase SelectMethod(BindingFlags bindingAttr, MethodBase[] match, Type[] types, ParameterModifier[] modifiers)
{
// 参数个数
var pcount = types == null ? 0 : types.Length;
foreach (var item in match)
{
// 参数比对
var mps = item.GetParameters();
// 无参数时
if (mps == null || mps.Length < 1)
if (pcount == 0)
return item;
else
continue;
// 比对参数个数
if (mps.Length != pcount) continue;
Boolean valid = true;
for (int i = 0; i < pcount; i++)
{
// 传入的参数类型为空或者Object,可以匹配所有参数
if (types[i] == null || types[i] == typeof(Object)) continue;
// 检查参数继承,不一定是精确匹配。任何一个不匹配就失败
//if (!types[i].IsAssignableFrom(mps[i].ParameterType))
if (mps[i].ParameterType != typeof(Object) && !mps[i].ParameterType.IsAssignableFrom(types[i]))
{
valid = false;
break;
}
}
if (valid) return item;
}
return null;
}
public override PropertyInfo SelectProperty(BindingFlags bindingAttr, PropertyInfo[] match, Type returnType, Type[] indexes, ParameterModifier[] modifiers)
{
throw new NotImplementedException();
}
}
#endregion
#region 获取属性或字段
//private PropertyInfoX[] _Properties;
///// <summary>属性集合</summary>
//public PropertyInfoX[] Properties
//{
// get
// {
// if (_Properties == null)
// {
// var pis = Type.GetProperties();
// if (pis == null || pis.Length < 1)
// _Properties = new PropertyInfoX[0];
// else
// _Properties = pis.Select(e => PropertyInfoX.Create(e)).ToArray();
// }
// return _Properties;
// }
//}
#endregion
#region 辅助方法
/// <summary>已重载。</summary>
/// <returns></returns>
public override string ToString()
{
String des = Description;
if (!String.IsNullOrEmpty(des))
return des;
else
return Type.FullName;
}
/// <summary>判断两个类型是否相同,避免引用加载和执行上下文加载的相同类型显示不同</summary>
/// <param name="type1"></param>
/// <param name="type2"></param>
/// <returns></returns>
public static Boolean Equal(Type type1, Type type2)
{
if (type1 == type2) return true;
return type1.FullName == type2.FullName && type1.AssemblyQualifiedName == type2.AssemblyQualifiedName;
}
/// <summary>类型转换</summary>
/// <param name="value">数值</param>
/// <param name="conversionType"></param>
/// <returns></returns>
public static Object ChangeType(object value, Type conversionType)
{
Type vtype = null;
if (value != null) vtype = value.GetType();
//if (vtype == conversionType || conversionType.IsAssignableFrom(vtype)) return value;
if (vtype == conversionType) return value;
var cx = Create(conversionType);
// 处理可空类型
if (!cx.IsValueType && IsNullable(conversionType))
{
if (value == null) return null;
conversionType = Nullable.GetUnderlyingType(conversionType);
}
if (cx.IsEnum)
{
if (vtype == _.String)
return Enum.Parse(conversionType, (String)value, true);
else
return Enum.ToObject(conversionType, value);
}
// 字符串转为货币类型,处理一下
if (vtype == _.String)
{
var str = (String)value;
if (Type.GetTypeCode(conversionType) == TypeCode.Decimal)
{
value = str.TrimStart(new Char[] { '$', '¥' });
}
else if (typeof(Type).IsAssignableFrom(conversionType))
{
return GetType((String)value, true);
}
// 字符串转为简单整型,如果长度比较小,满足32位整型要求,则先转为32位再改变类型
if (cx.IsInt && str.Length <= 10) return Convert.ChangeType(value.ToInt(), conversionType);
}
if (value != null)
{
// 尝试基础类型转换
switch (Type.GetTypeCode(conversionType))
{
case TypeCode.Boolean:
return value.ToBoolean();
case TypeCode.DateTime:
return value.ToDateTime();
case TypeCode.Double:
return value.ToDouble();
case TypeCode.Int16:
return (Int16)value.ToInt();
case TypeCode.Int32:
return value.ToInt();
case TypeCode.UInt16:
return (UInt16)value.ToInt();
case TypeCode.UInt32:
return (UInt32)value.ToInt();
default:
break;
}
if (value is IConvertible)
{
// 上海石头 发现这里导致Json序列化问题
// http://www.newlifex.com/showtopic-282.aspx
if (conversionType.IsGenericType && conversionType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
{
var nullableConverter = new NullableConverter(conversionType);
conversionType = nullableConverter.UnderlyingType;
}
value = Convert.ChangeType(value, conversionType);
}
//else if (conversionType.IsInterface)
// value = DuckTyping.Implement(value, conversionType);
}
else
{
// 如果原始值是null,要转为值类型,则new一个空白的返回
if (cx.IsValueType) value = CreateInstance(conversionType);
}
if (conversionType.IsAssignableFrom(vtype)) return value;
return value;
}
/// <summary>类型转换</summary>
/// <typeparam name="TResult"></typeparam>
/// <param name="value">数值</param>
/// <returns></returns>
public static TResult ChangeType<TResult>(Object value)
{
if (value is TResult) return (TResult)value;
return (TResult)ChangeType(value, typeof(TResult));
}
/// <summary>判断某个类型是否可空类型</summary>
/// <param name="type">类型</param>
/// <returns></returns>
public static Boolean IsNullable(Type type)
{
//if (type.IsValueType) return false;
if (type.IsGenericType && !type.IsGenericTypeDefinition &&
object.ReferenceEquals(type.GetGenericTypeDefinition(), typeof(Nullable<>))) return true;
return false;
}
///// <summary>
///// 获取可空类型的真是类型
///// </summary>
///// <param name="nullableType"></param>
///// <returns></returns>
//public static Type GetUnderlyingType(Type nullableType)
//{
// if (nullableType == null) throw new ArgumentNullException("nullableType");
// Type type = null;
// if (nullableType.IsGenericType && !nullableType.IsGenericTypeDefinition &&
// object.ReferenceEquals(nullableType.GetGenericTypeDefinition(), typeof(Nullable<>))) type = nullableType.GetGenericArguments()[0];
// return type;
//}
/// <summary>从参数数组中获取类型数组</summary>
/// <param name="args"></param>
/// <returns></returns>
public static Type[] GetTypeArray(object[] args)
{
if (args == null) return Type.EmptyTypes;
var typeArray = new Type[args.Length];
for (int i = 0; i < typeArray.Length; i++)
{
if (args[i] == null)
typeArray[i] = typeof(Object);
else
typeArray[i] = args[i].GetType();
}
return typeArray;
}
///// <summary>获取元素类型</summary>
///// <returns></returns>
//public Type GetElementType() { return GetElementType(Type); }
private static DictionaryCache<Type, Type> _elmCache = new DictionaryCache<Type, Type>();
/// <summary>获取一个类型的元素类型</summary>
/// <param name="type">类型</param>
/// <returns></returns>
public static Type GetElementType(Type type)
{
return _elmCache.GetItem(type, t =>
{
if (t.HasElementType) return t.GetElementType();
if (typeof(IEnumerable).IsAssignableFrom(type))
{
// 如果实现了IEnumerable<>接口,那么取泛型参数
foreach (var item in t.GetInterfaces())
{
if (item.IsGenericType && item.GetGenericTypeDefinition() == typeof(IEnumerable<>)) return item.GetGenericArguments()[0];
}
// 通过索引器猜测元素类型
var pi = type.GetProperty("Item", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (pi != null) return pi.PropertyType;
}
return null;
});
}
#endregion
#region 类型转换
/// <summary>类型转换</summary>
/// <param name="obj"></param>
/// <returns></returns>
public static implicit operator Type(TypeX obj)
{
return obj != null ? obj.Type : null;
}
/// <summary>类型转换</summary>
/// <param name="obj"></param>
/// <returns></returns>
public static implicit operator TypeX(Type obj)
{
return obj != null ? Create(obj) : null;
}
#endregion
#region 常用类型
/// <summary>常用类型</summary>
public static class _
{
/// <summary>类型</summary>
public static readonly Type Type = typeof(Type);
/// <summary>值类型</summary>
public static readonly Type ValueType = typeof(ValueType);
/// <summary>枚举类型</summary>
public static readonly Type Enum = typeof(Enum);
/// <summary>对象类型</summary>
public static readonly Type Object = typeof(Object);
/// <summary>字符串类型</summary>
public static readonly Type String = typeof(String);
}
#endregion
#region 原生扩展
private Boolean initBaseType;
private TypeX _BaseType;
/// <summary>基类。因计算类型基类极慢,故缓存</summary>
/// <remarks><see cref="P:Type.BaseType"/>实在太慢了</remarks>
public TypeX BaseType
{
get
{
if (!initBaseType)
{
var bt = Type.BaseType;
if (bt != null) _BaseType = TypeX.Create(bt);
initBaseType = true;
}
return _BaseType;
}
}
/// <summary>确定当前 <see cref="T:System.Type" /> 表示的类是否是从指定的 <see cref="T:System.Type" /> 表示的类派生的。</summary>
/// <returns>如果 Type 由 <paramref name="c" /> 参数表示并且当前的 Type 表示类,并且当前的 Type 所表示的类是从 <paramref name="c" /> 所表示的类派生的,则为 true;否则为 false。如果 <paramref name="c" /> 和当前的 Type 表示相同的类,则此方法还返回 false。</returns>
/// <param name="c">与当前的 Type 进行比较的 Type。</param>
/// <exception cref="T:System.ArgumentNullException"><paramref name="c" /> 参数为 null。</exception>
public Boolean IsSubclassOf(Type c)
{
var baseType = this;
if (baseType.Type != c)
{
while (baseType != null)
{
if (baseType.Type == c) return true;
baseType = baseType.BaseType;
}
return false;
}
return false;
}
///// <summary>确定当前的 <see cref="T:System.Type" /> 的实例是否可以从指定 Type 的实例分配。</summary>
///// <returns>如果满足下列任一条件,则为 true:<paramref name="c" /> 和当前 Type 表示同一类型;当前 Type 位于 <paramref name="c" /> 的继承层次结构中;当前 Type 是 <paramref name="c" /> 实现的接口;<paramref name="c" /> 是泛型类型参数且当前 Type 表示 <paramref name="c" /> 的约束之一。如果不满足上述任何一个条件或者 <paramref name="c" /> 为 null,则为 false。</returns>
///// <param name="c">与当前的 Type 进行比较的 Type。</param>
//public Boolean IsAssignableFrom(Type c)
//{
// var cx = Create(c);
// if (cx.IsSubclassOf(Type)) return true;
// return Type.IsAssignableFrom(c);
//}
/// <summary>基础类型代码</summary>
public TypeCode Code { get { return Type.GetTypeCode(Type); } }
/// <summary>获取一个值,该值指示当前的 <see cref="T:System.Type" /> 是否表示枚举。</summary>
/// <returns>如果当前 <see cref="T:System.Type" /> 表示枚举,则为 true;否则为 false。</returns>
public Boolean IsEnum { get { return IsSubclassOf(_.Enum); } }
/// <summary>是否整型。从Int16到UInt64共六种</summary>
public Boolean IsInt { get { var code = Code; return code >= TypeCode.Int16 && code <= TypeCode.UInt64; } }
private Boolean initIsValueType;
private Boolean _IsValueType;
/// <summary>获取一个值,通过该值指示 <see cref="T:System.Type" /> 是否为值类型。</summary>
/// <returns>如果 <see cref="T:System.Type" /> 是值类型,则为 true;否则为 false。</returns>
public Boolean IsValueType
{
get
{
if (!initIsValueType)
{
var type = Type;
_IsValueType = type != _.ValueType && type != _.Enum && IsSubclassOf(_.ValueType);
initIsValueType = true;
}
return _IsValueType;
}
}
#endregion
}
}
|