예제 #1
0
        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);
        }
예제 #2
0
 /// <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);
                 }
             }
         }
     }
 }
예제 #3
0
        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));
        }