17using DocumentFormat.OpenXml.Bibliography;
20using System.Collections;
21using System.Collections.Generic;
23using System.Reflection;
25using System.Threading.Tasks;
35 public static class ActivatorHelper
41 public static T CreateInstance<T>(
int elementCount = 0)
43 return (T)CreateInstance(typeof(T), elementCount);
150 public static dynamic CreateInstance(Type type,
int elementCount = 0)
153 type = ConverterHelper.GetConcreteType(type);
154 Type factoryType = typeof(GPAL);
156 bool isArray = type.IsArray;
157 bool isList = type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List<>);
159 if (isArray || isList)
161 Type elementType = isArray ? type.GetElementType() : type.GetGenericArguments()[0];
162 if (elementType ==
null)
164 string stackTrace = Environment.StackTrace;
165 Exception ex =
new InvalidOperationException($
"Cannot determine element type for type [{type.Name}].\n\nStack trace:\n{stackTrace}");
166 GPAL.PublishSimpleEvent(Enums.GPALEventType.EXCEPTION, $
"Unable to instantiate a [{type.Name}]",
null, Enums.GPALObjectType.None, ex);
170 object collectionInstance = isArray
171 ? Array.CreateInstance(elementType, elementCount)
172 : Activator.CreateInstance(type);
174 IList list = isList ? (IList)collectionInstance : null;
175 Array array = isArray ? (Array)collectionInstance : null;
177 if (elementType.Name.StartsWith(
"GPAL", StringComparison.OrdinalIgnoreCase))
179 var
property = GetGPALFactoryProperty(elementType);
180 if (property ==
null)
return null;
182 for (
int i = 0; i < elementCount; i++)
184 object elementInstance =
property.GetValue(
null);
186 array.SetValue(elementInstance, i);
188 list.Add(elementInstance);
192 return collectionInstance;
196 if (type.Name.StartsWith(
"GPAL", StringComparison.OrdinalIgnoreCase))
198 var
property = GetGPALFactoryProperty(type);
199 if (property ==
null)
return null;
201 return property.GetValue(
null);
206 var paramlessCtor = type.GetConstructor(Type.EmptyTypes);
207 if (paramlessCtor !=
null)
209 return paramlessCtor.Invoke(
null);
213 if (type.IsValueType)
215 return Activator.CreateInstance(type);
218 var constructors = type.GetConstructors(BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic);
219 if (constructors.Length == 0)
221 GPAL.PublishSimpleEvent(Enums.GPALEventType.ERROR, $
"No constructors found for type [{type.FullName}]. Don't know what you want to do.");
222 throw new InvalidOperationException($
"No constructors found for type [{type.FullName}]");
225 var targetCtor = constructors.OrderBy(c => c.GetParameters().Length).First();
226 var parameters = targetCtor.GetParameters();
227 var args =
new object[parameters.Length];
230 for (
int i = 0; i < parameters.Length; i++)
232 var paramType = parameters[i].ParameterType;
233 if (paramType == typeof(
string))
235 else if (paramType.IsValueType)
236 args[i] = Activator.CreateInstance(paramType);
237 else if (paramType.IsGenericType && (paramType.GetGenericTypeDefinition() == typeof(Dictionary<,>) || paramType.GetGenericTypeDefinition() == typeof(List<>)))
238 args[i] = Activator.CreateInstance(paramType);
243 return targetCtor.Invoke(args);
248 private static PropertyInfo GetGPALFactoryProperty(Type targetType)
250 if (targetType ==
null)
return null;
252 string baseName = targetType.IsGenericType
253 ? targetType.Name.Split(
'`')[0]
256 string propertyName = baseName.StartsWith(
"GPAL", StringComparison.OrdinalIgnoreCase)
257 ? baseName.Substring(4)
260 Type factoryType = typeof(GPAL);
261 var
property = factoryType.GetProperty(propertyName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
263 if (property ==
null)
265 string stackTrace = Environment.StackTrace;
266 Exception ex =
new InvalidOperationException(
267 $
"Factory getter [GPAL.{propertyName}] not found for type [{targetType.Name}].\n\nStack trace:\n{stackTrace}"
269 GPAL.PublishSimpleEvent(Enums.GPALEventType.EXCEPTION, $
"Unable to instantiate a [{targetType.Name}]",
null, Enums.GPALObjectType.None, ex);
273 Type factoryReturnType =
property.PropertyType;
274 if (!targetType.IsAssignableFrom(factoryReturnType) && !factoryReturnType.IsAssignableFrom(targetType))
276 string stackTrace = Environment.StackTrace;
277 Exception ex =
new InvalidOperationException(
278 $
"Factory getter [GPAL.{propertyName}] returns type [{factoryReturnType.Name}] which is not compatible with requested type [{targetType.Name}].\n\nStack trace:\n{stackTrace}"
280 GPAL.PublishSimpleEvent(Enums.GPALEventType.EXCEPTION, $
"Unable to instantiate a [{targetType.Name}]",
null, Enums.GPALObjectType.None, ex);