internal static Dictionary <string, IFastDeepClonerProperty> GetFastDeepClonerProperties(this Type primaryType) { if (!CachedPropertyInfo.ContainsKey(primaryType)) { var properties = new SafeValueType <string, IFastDeepClonerProperty>(); if (primaryType.GetTypeInfo().BaseType != null && primaryType.GetTypeInfo().BaseType.Name != "Object") { primaryType.GetRuntimeProperties().Where(x => properties.TryAdd(x.Name, new FastDeepClonerProperty(x))).ToList(); primaryType.GetTypeInfo().BaseType.GetRuntimeProperties().Where(x => properties.TryAdd(x.Name, new FastDeepClonerProperty(x))).ToList(); } else { primaryType.GetRuntimeProperties().Where(x => properties.TryAdd(x.Name, new FastDeepClonerProperty(x))).ToList(); } CachedPropertyInfo.Add(primaryType, properties); } return(CachedPropertyInfo[primaryType]); }
private static SafeValueType <string, IFastDeepClonerProperty> GetPropertiesInternal(Type primaryType, ICollection <PropertyInfo> ignorePropertyInfos) { var properties = new SafeValueType <string, IFastDeepClonerProperty>(); if (primaryType.GetTypeInfo().BaseType != null && primaryType.GetTypeInfo().BaseType.Name != "Object") { primaryType.GetRuntimeProperties().Except(ignorePropertyInfos).ToList() .ForEach(x => properties.TryAdd(x.Name, new FastDeepClonerProperty(x))); primaryType.GetTypeInfo().BaseType.GetRuntimeProperties().Except(ignorePropertyInfos).ToList() .ForEach(x => properties.TryAdd(x.Name, new FastDeepClonerProperty(x))); } else { primaryType.GetRuntimeProperties().Except(ignorePropertyInfos).ToList() .ForEach(x => properties.TryAdd(x.Name, new FastDeepClonerProperty(x))); } return(properties); }
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; } }