public static IWrappedList CreateListWrapper(object list) { ValidationUtils.ArgumentNotNull(list, "list"); Type listDefinition; if (ReflectionUtils.IsSubClass(list.GetType(), typeof(IList <>), out listDefinition)) { Type listItemType = ReflectionUtils.GetListItemType(listDefinition); // Activator.CreateInstance throws AmbiguousMatchException. Manually invoke constructor Func <Type, IList <object>, object> instanceCreator = (t, a) => { ConstructorInfo c = t.GetConstructor(new[] { listDefinition }); return(c.Invoke(new[] { list })); }; return((IWrappedList)ReflectionUtils.CreateGeneric(typeof(ListWrapper <>), new[] { listItemType }, instanceCreator, list)); } else if (list is IList) { return(new ListWrapper <object>((IList)list)); } else { throw new Exception("Can not create ListWrapper for type {0}.".FormatWith(CultureInfo.InvariantCulture, list.GetType())); } }
public static IList CreateAndPopulateList(Type listType, Action <IList> populateList) { ValidationUtils.ArgumentNotNull(listType, "listType"); ValidationUtils.ArgumentNotNull(populateList, "populateList"); IList list; Type readOnlyCollectionType; bool isReadOnlyOrFixedSize = false; if (listType.IsArray) { // have to use an arraylist when creating array // there is no way to know the size until it is finised list = new ArrayList(); isReadOnlyOrFixedSize = true; } else if (ReflectionUtils.IsSubClass(listType, typeof(ReadOnlyCollection <>), out readOnlyCollectionType)) { Type readOnlyCollectionContentsType = readOnlyCollectionType.GetGenericArguments()[0]; Type genericEnumerable = ReflectionUtils.MakeGenericType(typeof(IEnumerable <>), readOnlyCollectionContentsType); bool suitableConstructor = false; foreach (ConstructorInfo constructor in listType.GetConstructors()) { IList <ParameterInfo> parameters = constructor.GetParameters(); if (parameters.Count == 1) { if (genericEnumerable.IsAssignableFrom(parameters[0].ParameterType)) { suitableConstructor = true; break; } } } if (!suitableConstructor) { throw new Exception(string.Format("Readonly type {0} does not have a public constructor that takes a type that implements {1}.", listType, genericEnumerable)); } // can't add or modify a readonly list // use List<T> and convert once populated list = (IList)CreateGenericList(readOnlyCollectionContentsType); isReadOnlyOrFixedSize = true; } else if (typeof(IList).IsAssignableFrom(listType) && ReflectionUtils.IsInstantiatableType(listType)) { list = (IList)Activator.CreateInstance(listType); } else { throw new Exception(string.Format("Cannot create and populate list type {0}.", listType)); } populateList(list); // create readonly and fixed sized collections using the temporary list if (isReadOnlyOrFixedSize) { if (listType.IsArray) { list = ((ArrayList)list).ToArray(ReflectionUtils.GetListItemType(listType)); } else if (ReflectionUtils.IsSubClass(listType, typeof(ReadOnlyCollection <>))) { list = (IList)Activator.CreateInstance(listType, list); } } return(list); }