internal static ConstructorInfo GetConstructorInfo(this Type type, params object[] parameters) { var key = type.FullName + string.Join("", parameters?.Select(x => x.GetType())); if (ConstructorInfos.ContainsKey(key)) { return(ConstructorInfos.Get(key)); } #if !NETSTANDARD1_3 return(ConstructorInfos.GetOrAdd(key, parameters == null ? type.GetConstructor(Type.EmptyTypes) : type.GetConstructor(parameters.Select(x => x.GetType()).ToArray()))); #else ConstructorInfo constructor = null; foreach (var cr in type.GetTypeInfo().DeclaredConstructors) { var index = 0; var args = cr.GetParameters(); if (args.Length == parameters.Length) { var apply = true; foreach (var pr in args) { var prType = pr.ParameterType; var paramType = parameters[index].GetType(); if (prType != paramType) { try { Convert.ChangeType(parameters[index], prType); } catch { apply = false; break; } } index++; } if (apply) { constructor = cr; } } } return(ConstructorInfos.GetOrAdd(key, constructor)); #endif }
internal static Type GetFastType(this string typeName, string assembly) { if (string.IsNullOrEmpty(assembly)) { throw new Exception("AssemblyName cannot be empty"); } if (!assembly.ToLower().EndsWith(".dll")) { assembly += ".dll"; } var key = typeName + assembly; if (CachedStringTypes.ContainsKey(key)) { return(CachedStringTypes.Get(key)); } var type = Type.GetType($"{typeName}, {assembly.Substring(0, assembly.ToLower().IndexOf(".dll"))}"); if (type != null) { if (!CachedAssembly.ContainsKey(assembly)) { CachedAssembly.TryAdd(assembly, type.Assembly); } return(CachedStringTypes.GetOrAdd(key, type)); } else if (!CachedAssembly.ContainsKey(assembly)) { CachedAssembly.TryAdd(assembly, Assembly.LoadFrom(assembly)); } return(CachedStringTypes.GetOrAdd(key, CachedAssembly.Get(assembly).GetType(typeName, true, true))); }
internal static string GetFastDeepClonerIdentifier(this object o) { if (o == null) { return(null); } var type = o.GetType(); var p = CachedFastDeepClonerIdentifier.ContainsKey(type) ? CachedFastDeepClonerIdentifier[type] : CachedFastDeepClonerIdentifier.GetOrAdd(type, DeepCloner.GetFastDeepClonerProperties(type).FirstOrDefault(x => x.FastDeepClonerPrimaryIdentifire)); return(p == null ? null : type.FullName + type.Name + p.Name + p.FullName + p.GetValue(o)); }
internal static object Creator(this Type type, bool validateArgs = true, params object[] parameters) { try { var key = type.FullName + string.Join("", parameters?.Select(x => x.GetType().FullName)); var constructor = type.GetConstructorInfo(parameters ?? new object[0]); if (constructor == null && parameters?.Length > 0) { constructor = type.GetConstructorInfo(new object[0]); } if (constructor != null) { var constParam = constructor.GetParameters(); if (validateArgs && (parameters?.Any() ?? false)) { for (var i = 0; i < parameters.Length; i++) { if (constParam.Length <= i) { continue; } if (constParam[i].ParameterType != parameters[i].GetType()) { try { parameters[i] = Convert.ChangeType(parameters[i], constParam[i].ParameterType); } catch { // Ignore } } } } #if NETSTANDARD2_0 || NETSTANDARD1_3 || NETSTANDARD1_5 if (!constParam.Any()) { if (CachedConstructor.ContainsKey(key)) { return(CachedConstructor[key]()); } } else if (CachedConstructorWithParameter.ContainsKey(key)) { return(CachedConstructorWithParameter[key](parameters)); } if (!(parameters?.Any() ?? false)) { return(CachedConstructor.GetOrAdd(key, Expression.Lambda <Func <object> >(Expression.New(type)).Compile())()); } else { // Create a single param of type object[]. ParameterExpression param = Expression.Parameter(typeof(object[]), "args"); // Pick each arg from the params array and create a typed expression of them. Expression[] argsExpressions = new Expression[constParam.Length]; for (int i = 0; i < constParam.Length; i++) { Expression index = Expression.Constant(i); Type paramType = constParam[i].ParameterType; Expression paramAccessorExp = Expression.ArrayIndex(param, index); Expression paramCastExp = Expression.Convert(paramAccessorExp, paramType); argsExpressions[i] = paramCastExp; } return(CachedConstructorWithParameter.GetOrAdd(key, Expression.Lambda <Func <object[], object> >(Expression.New(constructor, argsExpressions), param).Compile())(parameters)); } #else if (!constParam.Any()) { if (CachedDynamicMethod.ContainsKey(key)) { return(CachedDynamicMethod[key]()); } } else if (CachedDynamicMethodWithParameters.ContainsKey(key)) { return(CachedDynamicMethodWithParameters[key](parameters)); } lock (CachedDynamicMethod) { var dynamicMethod = new System.Reflection.Emit.DynamicMethod("CreateInstance", type, (constParam.Any() ? new Type[] { typeof(object[]) } : Type.EmptyTypes), true); System.Reflection.Emit.ILGenerator ilGenerator = dynamicMethod.GetILGenerator(); if (constructor.GetParameters().Any()) { for (int i = 0; i < constParam.Length; i++) { Type paramType = constParam[i].ParameterType; ilGenerator.Emit(System.Reflection.Emit.OpCodes.Ldarg_0); // Push array (method argument) ilGenerator.Emit(System.Reflection.Emit.OpCodes.Ldc_I4, i); // Push i ilGenerator.Emit(System.Reflection.Emit.OpCodes.Ldelem_Ref); // Pop array and i and push array[i] if (paramType.IsValueType) { ilGenerator.Emit(System.Reflection.Emit.OpCodes.Unbox_Any, paramType); // Cast to Type t } else { ilGenerator.Emit(System.Reflection.Emit.OpCodes.Castclass, paramType); //Cast to Type t } } } //ilGenerator.Emit(System.Reflection.Emit.OpCodes.Nop); ilGenerator.Emit(System.Reflection.Emit.OpCodes.Newobj, constructor); //ilGenerator.Emit(System.Reflection.Emit.OpCodes.Stloc_1); // nothing ilGenerator.Emit(System.Reflection.Emit.OpCodes.Ret); if (!constParam.Any()) { return(CachedDynamicMethod.GetOrAdd(key, (ObjectActivator)dynamicMethod.CreateDelegate(typeof(ObjectActivator)))()); } else { return(CachedDynamicMethodWithParameters.GetOrAdd(key, (ObjectActivatorWithParameters)dynamicMethod.CreateDelegate(typeof(ObjectActivatorWithParameters)))(parameters)); } } #endif } else { #if !NETSTANDARD1_3 return(FormatterServices.GetUninitializedObject(type)); #else try { if (CachedConstructor.ContainsKey(key)) { return(CachedConstructor[key]()); } return(CachedConstructor.GetOrAdd(key, Expression.Lambda <Func <object> >(Expression.New(type)).Compile())()); } catch { throw new Exception("DeepClonerError: Default constructor is require for NETSTANDARD1_3 for type " + type.FullName); } #endif } } catch (Exception e) { throw e; } }
internal static ConstructorInfo GetConstructorInfo(this Type type, params object[] parameters) { IEnumerable <ConstructorInfo> constructors; var key = type.FullName + string.Join("", parameters?.Select(x => x.GetType())); if (ConstructorInfo.ContainsKey(key)) { return(ConstructorInfo.Get(key)); } #if !NETSTANDARD1_3 constructors = type.GetConstructors(); #else constructors = type.GetTypeInfo().DeclaredConstructors; #endif ConstructorInfo constructor = null; foreach (var cr in constructors) { var index = 0; var args = cr.GetParameters(); if (args.Length == parameters.Length) { var apply = true; foreach (var pr in args) { var prType = pr.ParameterType; var paramType = parameters[index].GetType(); if (prType != paramType) { try { if ((prType.IsInternalType() && paramType.IsInternalType())) { Convert.ChangeType(parameters[index], prType); } else { if (prType.GetTypeInfo().IsInterface&& paramType.GetTypeInfo().IsAssignableFrom(prType.GetTypeInfo())) { continue; } else { apply = false; break; } } } catch { apply = false; break; } } index++; } if (apply) { constructor = cr; } } } return(ConstructorInfo.GetOrAdd(key, constructor)); }
internal static object ConvertToInterface(this Type interfaceType, object item) { var type = item.GetType(); if (interfaceType.IsAssignableFrom(type)) { return(item); } var props = DeepCloner.GetFastDeepClonerProperties(type); var args = new SafeValueType <string, object>(); foreach (var iProp in DeepCloner.GetFastDeepClonerProperties(interfaceType)) { var p = DeepCloner.GetProperty(type, iProp.Name); if (p == null) { continue; } var value = p.GetValue(item); if (value == null || p.PropertyType == iProp.PropertyType) { args.Add(iProp.Name, value); continue; } try { if (iProp.PropertyType.IsInterface) { args.Add(iProp.Name, iProp.PropertyType.InterFaceConverter(value)); } else { args.Add(iProp.Name, Convert.ChangeType(value, DeepCloner.GetProperty(interfaceType, p.Name).PropertyType)); } } catch (Exception e) { var iType = iProp.PropertyType; throw new Exception($"Property {p.Name} has different type then the interface which is of type {iProp.PropertyType}. \n (Convert.ChangeType) could not convert from {p.PropertyType} to {iType}. \n Orginal Exception: {e.Message}"); } } var key = $"{(type.IsAnonymousType() ? string.Join(" | ", props.Select(x => x.FullName).ToArray()) : type.FullName)} | {interfaceType.FullName}"; var newtype = CachedConvertedObjectToInterface.ContainsKey(key) ? CachedConvertedObjectToInterface[key] : CachedConvertedObjectToInterface.GetOrAdd(key, FastDeepCloner.ConvertToInterfaceTypeGenerator.Convert(interfaceType, type)); var returnValue = Creator(newtype, false, args.Values.ToArray()); var constructor = GetConstructorInfo(newtype, args.Values.ToArray()); if (constructor == null) { foreach (var p in args) { DeepCloner.GetProperty(newtype, p.Key).SetValue(returnValue, args[p.Key]); } } return(returnValue); }