/***************************************************/ public static string Path(this MethodBase method, bool userReturnTypeForCreate = true, bool useExtentionType = false) { if (method == null) { Compute.RecordError("Cannot query the path of a null method base."); return(null); } Type type = method.DeclaringType; if (userReturnTypeForCreate && type.Name == "Create" && method is MethodInfo) { Type returnType = ((MethodInfo)method).ReturnType.UnderlyingType().Type; if (returnType.Namespace.StartsWith("BH.")) { type = returnType; } } else if (useExtentionType && method.IsDefined(typeof(ExtensionAttribute), false)) { ParameterInfo[] parameters = method.GetParameters(); if (parameters.Length > 0) { type = parameters[0].ParameterType; } } return(type.ToText(true, true)); }
/***************************************************/ /**** Public Methods ****/ /***************************************************/ public static string UnqualifiedName(string qualifiedName) { if (qualifiedName == null) { Compute.RecordError("Cannot extract the unqualified name from a null string."); return(""); } int openIndex = qualifiedName.IndexOf('['); int closeIndex = qualifiedName.LastIndexOf(']'); if (openIndex < 0 || closeIndex < 0) { return(qualifiedName.Split(',').First()); } string inside = qualifiedName.Substring(openIndex + 1, closeIndex - openIndex - 1); List <int> cuts = FindLevelZero(inside, ',', '[', ']'); List <string> parts = SplitByIndices(inside, cuts); for (int i = 0; i < parts.Count; i++) { parts[i] = UnqualifiedName(parts[i].Trim('[', ']', ' ')); } return(qualifiedName.Substring(0, openIndex + 1) + parts.Aggregate((a, b) => a + ',' + b) + "]"); }
/***************************************************/ /**** Public Methods ****/ /***************************************************/ public static List <Type> UsedTypes(this MethodBase method, bool onlyBHoM = false) { try { IEnumerable <Type> varTypes = new List <Type>(); MethodBody body = method.GetMethodBody(); if (body != null) { varTypes = method.GetMethodBody().LocalVariables.Select(x => x.LocalType); } IEnumerable <Type> methodTypes = method.UsedMethods(onlyBHoM).Select(x => x.DeclaringType); IEnumerable <Type> paramTypes = method.GetParameters().Select(x => x.ParameterType); IEnumerable <Type> types = methodTypes.Union(paramTypes).Union(varTypes).Distinct(); if (onlyBHoM) { return(types.Where(x => x.Namespace.StartsWith("BH.")).ToList()); } else { return(types.ToList()); } } catch (Exception e) { Compute.RecordError(method.ToString() + " failed t oextract its types.\nError: " + e.ToString()); return(new List <Type>()); } }
/***************************************************/ /**** Public Methods ****/ /***************************************************/ public static Type Type(string name) { Dictionary <string, List <Type> > typeDictionary = Query.BHoMTypeDictionary(); List <Type> types = null; if (!typeDictionary.TryGetValue(name, out types)) { Compute.RecordError($"A type corresponding to {name} cannot be found."); return(null); } else if (types.Count == 1) { return(types[0]); } else { string message = "Ambiguous match: Multiple types correspond the the name provided: \n"; foreach (Type type in types) { message += "- " + type.FullName + "\n"; } Compute.RecordError(message); return(null); } }
/***************************************************/ /**** Public Methods ****/ /***************************************************/ public static List <MethodBase> UsedMethods(this MethodBase method, bool onlyBHoM = false) { try { if (method.GetMethodBody() == null) { return(new List <MethodBase>()); } IEnumerable <MethodBase> methods = Disassembler.GetInstructions(method) .Select(x => x.Operand) .OfType <MethodBase>() .Distinct() .Where(x => x.DeclaringType.Namespace != null) .SelectMany(x => x.IsAutoGenerated() ? x.UsedMethods(onlyBHoM) : new List <MethodBase> { x }); if (onlyBHoM) { return(methods.Where(x => x.DeclaringType.Namespace.StartsWith("BH.")).ToList()); } else { return(methods.ToList()); } } catch (Exception e) { Compute.RecordError("Method " + method.DeclaringType.Namespace + "." + method.Name + " failed to extract the information about the method.\nError: " + e.ToString()); return(new List <MethodBase>()); } }
public static string PropertyAbbreviation(this object obj, string propName) { if (obj == null) { Compute.RecordError("Cannot query the property abbreviation of a null object."); return(""); } if (propName == null) { Compute.RecordError("Cannot query the property abbreviation where the property name is null."); return(""); } System.Reflection.PropertyInfo prop = obj.GetType().GetProperty(propName); if (prop != null) { object[] attributes = prop.GetCustomAttributes(typeof(AbbreviationAttribute), false); if (attributes.Length == 1) { AbbreviationAttribute attribute = (AbbreviationAttribute)attributes[0]; if (attribute != null) { return(attribute.Name); } } } return(""); }
public static Type MakeFromGeneric(this Type genericType) { if (genericType == null) { Compute.RecordError("Cannot make generic from null type."); return(null); } if (genericType.IsGenericParameter) { Type[] constrains = genericType.GetGenericParameterConstraints(); if (constrains.Length == 0) { return(typeof(object)); } else { return(MakeFromGeneric(constrains[0])); } } else if (genericType.ContainsGenericParameters) { if (genericType.GetGenericArguments().Any(x => x.IsGenericParameter && x.GetGenericParameterConstraints().Any(c => c == genericType))) { return(genericType.GetGenericTypeDefinition().MakeGenericType(new Type[] { typeof(object) })); } Type[] constrains = genericType.GetGenericArguments().Select(x => MakeFromGeneric(x)).ToArray(); return(genericType.GetGenericTypeDefinition().MakeGenericType(constrains)); } else { return(genericType); } }
/***************************************************/ public static Type GenericType(string name, bool silent = false) { if (name == null) { Compute.RecordError("Cannot create a type from a null string."); return(null); } string[] parts = name.Split('<', '>', ',').Select(x => x.Trim()).ToArray(); string[] arguments = parts.Skip(1).Where(x => x.Length > 0).ToArray(); Type typeDefinition = Type(parts[0] + "`" + arguments.Length); if (typeDefinition == null) { return(null); } try { return(typeDefinition.MakeGenericType(arguments.Select(x => Type(x)).ToArray())); } catch { return(null); } }
/***************************************************/ /**** Public Methods ****/ /***************************************************/ public static List <string> SplitByIndices(string text, List <int> indices) { if (text == null) { Compute.RecordError("Cannot split a null string."); return(new List <string>()); } if (indices == null) { Compute.RecordWarning("The 'indices' input is null and was replaced by an empty list"); indices = new List <int>(); } int previousIndex = 0; List <string> result = new List <string>(); foreach (int index in indices.OrderBy(x => x)) { result.Add(text.Substring(previousIndex, index - previousIndex)); previousIndex = index + 1; } result.Add(text.Substring(previousIndex)); return(result); }
/***************************************************/ /**** Public Methods ****/ /***************************************************/ public static string Path(this Type type) { if (type == null) { Compute.RecordError("Cannot query the path of a null type."); return(null); } return(type.Namespace); }
/*************************************/ /**** Public Methods ****/ /*************************************/ public static MethodInfo MethodInfo(this Type declaringType, string methodName, List <Type> paramTypes) { if (declaringType == null) { Compute.RecordError("Cannot create a method info from a null type."); return(null); } if (methodName == null) { Compute.RecordError("Cannot create a method info from a null method name."); return(null); } if (paramTypes == null) { Compute.RecordWarning("The 'paramTypes' input is null and was replaced by an empty list"); paramTypes = new List <Type>(); } MethodInfo foundMethod = null; List <MethodInfo> methods = declaringType.GetMethods(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly).ToList(); for (int k = 0; k < methods.Count; k++) { MethodInfo method = methods[k]; if (method.Name == methodName) { ParameterInfo[] parameters = method.GetParameters(); if (parameters.Length == paramTypes.Count) { if (method.ContainsGenericParameters) { Type[] generics = method.GetGenericArguments().Select(x => x.MakeFromGeneric()).ToArray(); method = method.MakeGenericMethod(generics); parameters = method.GetParameters(); } bool matching = true; for (int i = 0; i < paramTypes.Count; i++) { matching &= (paramTypes[i] == null || parameters[i].ParameterType == paramTypes[i]); } if (matching) { foundMethod = method; break; } } } } return(foundMethod); }
/***************************************************/ /**** Public Methods ****/ /***************************************************/ public static Type Type(string name, bool silent = false) { if (name == null) { Compute.RecordError("Cannot create a type from a null string."); return(null); } Dictionary <string, List <Type> > typeDictionary = Query.BHoMTypeDictionary(); if (name.Contains('<')) { return(GenericType(name, silent)); } List <Type> types = null; if (!typeDictionary.TryGetValue(name, out types)) { Type type = System.Type.GetType(name); if (type == null && name.EndsWith("&")) { type = Type(name.TrimEnd(new char[] { '&' }), true); if (type != null) { type = type.MakeByRefType(); } } if (type == null && !silent) { Compute.RecordError($"A type corresponding to {name} cannot be found."); } return(type); } else if (types.Count == 1) { return(types[0]); } else if (!silent) { string message = "Ambiguous match: Multiple types correspond the the name provided: \n"; foreach (Type type in types) { message += "- " + type.FullName + "\n"; } Compute.RecordError(message); } return(null); }
/***************************************************/ public static List <Type> AllTypes(string name, bool silent = false) { if (name == null) { Compute.RecordError("Cannot create types from a null string."); return(new List <Type>()); } List <Type> typeList = new List <Type>(); if (name.StartsWith("BH.Engine")) { typeList = Query.EngineTypeList(); } else if (name.StartsWith("BH.Adapter")) { typeList = Query.AdapterTypeList(); } else if (name.StartsWith("BH.oM")) { typeList = Query.BHoMTypeList(); } else { typeList = Query.AllTypeList(); } List <Type> types = typeList.Where(x => x.AssemblyQualifiedName.Contains(name)).ToList(); if (types.Count != 0) { return(types); } else { //No method found in dictionary, try System.Type Type type = System.Type.GetType(name); if (type == null) { if (!silent) { Compute.RecordError($"A type corresponding to {name} cannot be found."); } return(new List <Type>()); } return(new List <Type> { type }); } }
public static MethodInfo MakeFromGeneric(this MethodInfo genericMethod) { if (genericMethod == null) { Compute.RecordError("Cannot make generic from a null method."); return(null); } if (genericMethod.ContainsGenericParameters) { Type[] types = genericMethod.GetGenericArguments().Select(x => x.MakeFromGeneric()).ToArray(); genericMethod = genericMethod.MakeGenericMethod(types); } return(genericMethod); }
/***************************************************/ public static Func <object[], object> ToFunc(this ConstructorInfo ctor) { if (ctor == null) { Compute.RecordError("Cannot convert constructor info to func if the constructor is null."); return(null); } ParameterExpression lambdaInput = Expression.Parameter(typeof(object[]), "x"); Expression[] inputs = ctor.GetParameters().Select((x, i) => Expression.Convert(Expression.ArrayIndex(lambdaInput, Expression.Constant(i)), x.ParameterType)).ToArray(); NewExpression constructorExpression = Expression.New(ctor as ConstructorInfo, inputs); return(Expression.Lambda <Func <object[], object> >(Expression.Convert(constructorExpression, typeof(object)), lambdaInput).Compile()); }
/***************************************************/ public static Func <object[], object> ToFunc(this MethodInfo method) { if (method == null) { Compute.RecordError("Cannot convert method info to func if method is null."); return(null); } ParameterExpression lambdaInput = Expression.Parameter(typeof(object[]), "x"); Expression[] inputs = method.GetParameters().Select((x, i) => Expression.Convert(Expression.ArrayIndex(lambdaInput, Expression.Constant(i)), x.ParameterType.GetTypeIfRef())).ToArray(); MethodCallExpression methodExpression; if (method.IsStatic) { methodExpression = Expression.Call(method, inputs); if (method.ReturnType == typeof(void)) { return(Expression.Lambda <Action <object[]> >(Expression.Convert(methodExpression, typeof(void)), lambdaInput).Compile().ToFunc()); } else { return(Expression.Lambda <Func <object[], object> >(Expression.Convert(methodExpression, typeof(object)), lambdaInput).Compile()); } } else { ParameterExpression instanceParameter = Expression.Parameter(typeof(object), "instance"); Expression instanceInput = Expression.Convert(instanceParameter, method.DeclaringType); methodExpression = Expression.Call(instanceInput, method, inputs); if (method.ReturnType == typeof(void)) { return(Expression.Lambda <Action <object, object[]> >( Expression.Convert(methodExpression, typeof(void)), new ParameterExpression[] { instanceParameter, lambdaInput } ).Compile().ToFunc()); } else { return(Expression.Lambda <Func <object, object[], object> >( Expression.Convert(methodExpression, typeof(object)), new ParameterExpression[] { instanceParameter, lambdaInput } ).Compile().ToFunc()); } } }
/***************************************************/ /**** Public Methods ****/ /***************************************************/ public static Type Type(string name, bool silent = false) { Dictionary <string, List <Type> > typeDictionary = Query.BHoMTypeDictionary(); if (name.Contains('<')) { return(GenericType(name, silent)); } List <Type> types = null; if (!typeDictionary.TryGetValue(name, out types)) { Type type = System.Type.GetType(name); if (type != null) { return(type); } else { if (!silent) { Compute.RecordError($"A type corresponding to {name} cannot be found."); } return(null); } } else if (types.Count == 1) { return(types[0]); } else if (!silent) { string message = "Ambiguous match: Multiple types correspond the the name provided: \n"; foreach (Type type in types) { message += "- " + type.FullName + "\n"; } Compute.RecordError(message); } return(null); }
public static bool IsAssignableFromIncludeGenerics(this Type assignableTo, Type assignableFrom) { if (assignableTo == null || assignableFrom == null) { Compute.RecordError("Cannot assign to or from null types."); return(false); } //Check if standard IsAssignableFrom works. if (assignableTo.IsAssignableFrom(assignableFrom)) { return(true); } //If not, check if the argument is generic, and if so, use the IsAssignableToGenericType method to check if it can be assigned. else { return(assignableTo.IsGenericType && assignableFrom.IsAssignableToGenericType(assignableTo.GetGenericTypeDefinition())); } }
/***************************************************/ public static bool RecordEvent(Event newEvent) { if (newEvent == null) { Compute.RecordError("Cannot record a null event."); return(false); } string trace = System.Environment.StackTrace; newEvent.StackTrace = string.Join("\n", trace.Split('\n').Skip(4).ToArray()); Log log = Query.DebugLog(); log.AllEvents.Add(newEvent); log.CurrentEvents.Add(newEvent); return(true); }
/***************************************************/ public static Type EngineType(string name, bool silent = false) { if (name == null) { Compute.RecordError("Cannot create a type from a null string."); return(null); } List <Type> methodTypeList = Query.EngineTypeList(); List <Type> types = methodTypeList.Where(x => x.AssemblyQualifiedName.StartsWith(name)).ToList(); if (types.Count == 1) { return(types[0]); } else { //Unique method not found in list, check if it can be extracted using the system Type Type type = System.Type.GetType(name, silent); if (type == null && !silent) { if (types.Count == 0) { Compute.RecordError($"A type corresponding to {name} cannot be found."); } else { string message = "Ambiguous match: Multiple types correspond the the name provided: \n"; foreach (Type t in types) { message += "- " + t.FullName + "\n"; } message += "To get a Engine type from a specific Assembly, try adding ', NameOfTheAssmebly' at the end of the name string, or use the AllEngineTypes method to retreive all the types."; Compute.RecordError(message); } } return(type); } }
/***************************************************/ /**** Public Methods ****/ /***************************************************/ public static MethodInfo MakeGenericFromInputs(this MethodInfo method, List <Type> inputTypes) { if (method == null) { Compute.RecordError("Cannot make generic from inputs of a null method."); return(null); } if (inputTypes == null) { Compute.RecordWarning("The 'inputTypes' input is null and was replaced by an empty list"); return(null); } if (!method.IsGenericMethod) { return(method); } List <Type> paramTypes = method.GetParameters().Select(x => x.ParameterType).ToList(); // Get where the generic arguments are actually used Dictionary <string, Type> dic = new Dictionary <string, Type>(); for (int i = 0; i < paramTypes.Count; i++) { Type paramType = paramTypes[i]; if (paramType.IsGenericType || paramType.IsGenericParameter) { MatchGenericParameters(paramTypes[i], inputTypes[i], ref dic); } } // Actually make the generic method List <Type> actualTypes = method.GetGenericArguments().Select(x => dic.ContainsKey(x.Name) ? dic[x.Name] : typeof(object)).ToList(); return(method.MakeGenericMethod(actualTypes.ToArray())); }
public static object SetPropertyValue(this object obj, string propName, object value = null) { if (obj == null) { Compute.RecordError("Cannot set the property value of a null object."); return(obj); } if (propName == null) { Compute.RecordError("Cannot set the property value where the property name is null."); return(obj); } object toChange = obj; if (propName.Contains(".")) { string[] props = propName.Split('.'); for (int i = 0; i < props.Length - 1; i++) { toChange = toChange.PropertyValue(props[i]); if (toChange == null) { break; } } propName = props[props.Length - 1]; } System.Reflection.PropertyInfo prop = toChange.GetType().GetProperty(propName); if (prop != null) { if (!prop.CanWrite) { Engine.Reflection.Compute.RecordError("This property doesn't have a public setter so it is not possible to modify it."); return(obj); } Type propType = prop.PropertyType; if (value == null) { if (propType == typeof(string)) { value = ""; } else if (propType.IsValueType || typeof(IEnumerable).IsAssignableFrom(propType)) { value = Activator.CreateInstance(propType); } } if (propType.IsEnum && value is string) { string enumName = (value as string).Split('.').Last(); try { object enumValue = Enum.Parse(propType, enumName); if (enumValue != null) { value = enumValue; } } catch { Engine.Reflection.Compute.RecordError($"An enum of type {propType.ToText(true)} does not have a value of {enumName}"); } } if (propType == typeof(DateTime) && value is string) { DateTime date; if (DateTime.TryParse(value as string, out date)) { value = date; } else { Engine.Reflection.Compute.RecordError($"The value provided for {propName} is not a valid DateTime."); value = DateTime.MinValue; } } if (propType == typeof(Type) && value is string) { value = Create.Type(value as string); } if (value != null) { if (value.GetType() != propType && value.GetType().GenericTypeArguments.Length > 0 && propType.GenericTypeArguments.Length > 0) { value = Modify.CastGeneric(value as dynamic, propType.GenericTypeArguments[0]); } if (value.GetType() != propType) { ConstructorInfo constructor = propType.GetConstructor(new Type[] { value.GetType() }); if (constructor != null) { value = constructor.Invoke(new object[] { value }); } } } prop.SetValue(toChange, value); return(obj); } else { SetValue(toChange as dynamic, propName, value); return(obj); } }