private static Array DeepCloneArray(Type arrayHolderType, Array originalArray) { Mandate.ParameterNotNull(arrayHolderType, "arrayHolderType"); Mandate.ParameterNotNull(originalArray, "originalArray"); var elementType = arrayHolderType.GetElementType(); var newArray = CreateArray(originalArray, elementType); for (var index = 0; index < originalArray.Length; index++) { if (TypeFinder.IsImplicitValueType(elementType)) { newArray.SetValue(originalArray.GetValue(index), index); } else { newArray.SetValue(DeepCopy(originalArray.GetValue(index)), index); } } return(newArray); }
/// <summary> /// Sets a value on a member of an instance <paramref name="target"/> of type <paramref name="sourceType"/>. /// </summary> /// <param name="member">The member.</param> /// <param name="sourceType">Type of the source.</param> /// <param name="target">The target.</param> /// <param name="sourceValue">The source value.</param> /// <param name="setter">The setter.</param> /// <param name="outerLoopRecurseCount">The outer loop recursion count.</param> private static void SetValue(MemberInfo member, Type sourceType, object target, object sourceValue, Action <object, object> setter, int outerLoopRecurseCount) { if (TypeFinder.IsImplicitValueType(sourceType)) { setter.Invoke(target, sourceValue); } else { if (sourceValue == null) { setter.Invoke(target, null); } else { if (sourceType.IsArray) { // It's an array, so we need to run this method for each item in the array and return an array of the same type var newArray = DeepCloneArray(sourceType, sourceValue as Array); setter.Invoke(target, newArray); return; } else { // Certain types are not cloneable, e.g. delegates if (IsNotCloneable(member)) { // Just set the value to be the same setter.Invoke(target, sourceValue); } else { // Need to get the actual type, not the signature one (e.g. the runtime type not the interface) var reflectedType = sourceValue.GetType(); CloneOf <object> deepCopy = DeepCopy(sourceValue, reflectedType, recurseCount: outerLoopRecurseCount + 1); setter.Invoke(target, deepCopy.Value); } } } } }
private static Func <object> GetObjectFactory(Type type) { if (type.IsInterface) { throw new InvalidOperationException("Cannot instantiate an interface ({0})".InvariantFormat(type.FullName)); } var isFullyTrusted = AppDomain.CurrentDomain.IsFullyTrusted; var constructor = type.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) .Where(x => x.GetParameters().Count() == 0 && (isFullyTrusted || (!isFullyTrusted && !x.IsSecurityCritical && !x.IsSecuritySafeCritical))) .FirstOrDefault(); if (constructor != null) { // This catch block is here because there are certain types of constructor that I can't grab via properties on ConstructorInfo // for example NullViewLocationCache is a sealed internal type with no constructor, yet a constructor is found using the above // method! try { return(() => constructor.Invoke(new object[0])); } catch (SecurityException ex) { LogSecurityException(type, isFullyTrusted, ex); } catch (MemberAccessException ex) { ThrowIfFullTrust(type, isFullyTrusted, ex); } } if (isFullyTrusted) { return(() => FormatterServices.GetUninitializedObject(type)); } // We're in partial trust, but haven't found a default constructor, so find the first constructor with nullable parameter types var nearestConstructor = type.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) .OrderBy(x => x.GetParameters().Count()) .FirstOrDefault(); if (nearestConstructor != null) { var paramValues = nearestConstructor.GetParameters().Select(x => TypeFinder.IsImplicitValueType(x.ParameterType) ? x.ParameterType.GetDefaultValue() : CreateObject(x.ParameterType)).ToArray(); try { return(() => nearestConstructor.Invoke(paramValues)); } catch (SecurityException ex) { LogSecurityException(type, isFullyTrusted, ex); } catch (MemberAccessException ex) { ThrowIfFullTrust(type, isFullyTrusted, ex); } } throw new InvalidOperationException( "Cannot find a default constructor for {0}, and since this AppDomain is not fully trusted, also tried to find another constructor, but that failed too. Come to think of it, how do YOU make this object?".InvariantFormat(type.FullName)); }