From 2004f5644e7c25529676d06a2fb9aec55bd43cb0 Mon Sep 17 00:00:00 2001 From: Eduardo Pignatelli Date: Thu, 8 Aug 2019 11:35:44 +0100 Subject: [PATCH 01/28] initial prototype --- .../Compute/LoadAllAssemblies.cs | 3 +- Reflection_Engine/Query/MethodList.cs | 27 +++++ Serialiser_Engine/Convert/Bson.cs | 1 + Serialiser_Engine/Create/Delegate.cs | 65 +++++++++++ .../BsonSerializers/DelegateSerializser.cs | 104 ++++++++++++++++++ .../BsonSerializers/ObjectSerializer.cs | 2 + Serialiser_Engine/Serialiser_Engine.csproj | 2 + 7 files changed, 203 insertions(+), 1 deletion(-) create mode 100644 Serialiser_Engine/Create/Delegate.cs create mode 100644 Serialiser_Engine/Objects/BsonSerializers/DelegateSerializser.cs diff --git a/Reflection_Engine/Compute/LoadAllAssemblies.cs b/Reflection_Engine/Compute/LoadAllAssemblies.cs index 82890a1eb..cf67df5e1 100644 --- a/Reflection_Engine/Compute/LoadAllAssemblies.cs +++ b/Reflection_Engine/Compute/LoadAllAssemblies.cs @@ -62,7 +62,8 @@ public static void LoadAllAssemblies(string folder = "") continue; } - if (file.EndsWith("oM.dll") || file.EndsWith("_Engine.dll") || file.EndsWith("_Adapter.dll") || file.EndsWith("_Test.dll")) + if (file.EndsWith("oM.dll") || file.EndsWith("_Engine.dll") || file.EndsWith("_Adapter.dll") || + file.EndsWith("_Test.dll") || file.EndsWith("_External.dll")) { try { diff --git a/Reflection_Engine/Query/MethodList.cs b/Reflection_Engine/Query/MethodList.cs index 92e74e622..076ea5089 100644 --- a/Reflection_Engine/Query/MethodList.cs +++ b/Reflection_Engine/Query/MethodList.cs @@ -59,6 +59,17 @@ public static List AllMethodList() return m_AllMethodList; } + /***************************************************/ + + public static List ExternalMethodList() + { + // If the dictionary exists already return it + if (m_ExternamMethodList == null || m_ExternamMethodList.Count <= 0) + ExtractAllMethods(); + + return m_ExternamMethodList; + } + /***************************************************/ /**** Private Methods ****/ @@ -90,6 +101,10 @@ private static void ExtractAllMethods() m_BHoMMethodList.AddRange(typeMethods.Where(x => x.IsLegal())); } + if (type.Name == "External") + { + + } // Get everything StoreAllMethods(type); } @@ -101,6 +116,17 @@ private static void ExtractAllMethods() StoreAllMethods(type); } } + else if (name.EndsWith("_External")) + { + foreach (Type type in asm.GetTypes()) + { + if (type is BHoMAddin) + (BHoMAddin)type).ExternalMethods(); + List externalDelegates = type.GetMethod("ExternalMethods")?.Invoke(null, null) as List; + if (externalDelegates != null) + m_ExternamMethodList.AddRange(externalDelegates); + } + } } catch (Exception) { @@ -128,6 +154,7 @@ private static void StoreAllMethods(Type type) private static List m_BHoMMethodList = new List(); private static List m_AllMethodList = new List(); + private static List m_ExternamMethodList = new List(); /***************************************************/ } diff --git a/Serialiser_Engine/Convert/Bson.cs b/Serialiser_Engine/Convert/Bson.cs index 92e03eb36..e2e0e4a5f 100644 --- a/Serialiser_Engine/Convert/Bson.cs +++ b/Serialiser_Engine/Convert/Bson.cs @@ -125,6 +125,7 @@ private static void RegisterTypes() BsonSerializer.RegisterSerializer(typeof(object), new BH_ObjectSerializer()); BsonSerializer.RegisterSerializer(typeof(System.Drawing.Color), new ColourSerializer()); BsonSerializer.RegisterSerializer(typeof(MethodBase), new MethodBaseSerializer()); + BsonSerializer.RegisterSerializer(typeof(Delegate), new DelegateSerializer()); BsonSerializer.RegisterSerializer(typeof(Guid), new GuidSerializer(BsonType.String)); BsonSerializer.RegisterSerializer(typeof(CustomObject), new CustomObjectSerializer()); BsonSerializer.RegisterSerializer(typeof(Enum), new EnumSerializer()); diff --git a/Serialiser_Engine/Create/Delegate.cs b/Serialiser_Engine/Create/Delegate.cs new file mode 100644 index 000000000..703f22841 --- /dev/null +++ b/Serialiser_Engine/Create/Delegate.cs @@ -0,0 +1,65 @@ +/* + * This file is part of the Buildings and Habitats object Model (BHoM) + * Copyright (c) 2015 - 2018, the respective contributors. All rights reserved. + * + * Each contributor holds copyright over their respective contributions. + * The project versioning (Git) records all such contribution source information. + * + * + * The BHoM is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3.0 of the License, or + * (at your option) any later version. + * + * The BHoM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + */ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; + +namespace BH.Engine.Serialiser +{ + public static partial class Create + { + /*******************************************/ + /**** Public Methods ****/ + /*******************************************/ + + public static Delegate Delegate(this MethodInfo method, Type target) + { + ParameterInfo[] parameters = method.GetParameters(); + + List parameterTypes = parameters.Select(x => x.ParameterType).ToList(); + parameterTypes.Add(method.ReturnType); + if (!method.IsStatic) + parameterTypes.Insert(0, target); + + object firstArgument = method.IsStatic ? null : target ?? method.DeclaringType; + + if (method.IsGenericMethod || method.ContainsGenericParameters) + { + //Type[] types = method.GetGenericArguments().Select(x => GetConstructedType(x)).ToArray(); + //method = method.MakeGenericMethod(types); + //return method; + return null; + } + + Type delegateType = Expression.GetDelegateType(parameterTypes.ToArray()); + Delegate @delegate = System.Delegate.CreateDelegate(delegateType, method); + + + return @delegate; + } + + /*******************************************/ + } +} diff --git a/Serialiser_Engine/Objects/BsonSerializers/DelegateSerializser.cs b/Serialiser_Engine/Objects/BsonSerializers/DelegateSerializser.cs new file mode 100644 index 000000000..3066b4bdd --- /dev/null +++ b/Serialiser_Engine/Objects/BsonSerializers/DelegateSerializser.cs @@ -0,0 +1,104 @@ +/* + * This file is part of the Buildings and Habitats object Model (BHoM) + * Copyright (c) 2015 - 2018, the respective contributors. All rights reserved. + * + * Each contributor holds copyright over their respective contributions. + * The project versioning (Git) records all such contribution source information. + * + * + * The BHoM is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3.0 of the License, or + * (at your option) any later version. + * + * The BHoM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + */ + +using MongoDB.Bson; +using MongoDB.Bson.IO; +using MongoDB.Bson.Serialization; +using MongoDB.Bson.Serialization.Conventions; +using MongoDB.Bson.Serialization.Serializers; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Reflection; + +namespace BH.Engine.Serialiser.BsonSerializers +{ + public class DelegateSerializer : SerializerBase, IBsonPolymorphicSerializer + { + /*******************************************/ + /**** Properties ****/ + /*******************************************/ + + public bool IsDiscriminatorCompatibleWithObjectSerializer { get; } = true; + + + /*******************************************/ + /**** Public Methods ****/ + /*******************************************/ + + public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, Delegate value) + { + var bsonWriter = context.Writer; + bsonWriter.WriteStartDocument(); + + var discriminator = m_DiscriminatorConvention.GetDiscriminator(typeof(object), typeof(Delegate)); + bsonWriter.WriteName(m_DiscriminatorConvention.ElementName); + BsonValueSerializer.Instance.Serialize(context, discriminator); + + bsonWriter.WriteName("Method"); + bsonWriter.WriteString(value.Method.ToJson()); + + bsonWriter.WriteName("Target"); + bsonWriter.WriteString(value.Target?.ToJson() ?? ""); + + bsonWriter.WriteEndDocument(); + } + + /*******************************************/ + + public override Delegate Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) + { + var bsonReader = context.Reader; + bsonReader.ReadStartDocument(); + + string text = bsonReader.ReadName(); + if (text == m_DiscriminatorConvention.ElementName) + bsonReader.SkipValue(); + + bsonReader.ReadName(); + string methodName = bsonReader.ReadString(); + + bsonReader.ReadName(); + string targetName = bsonReader.ReadString(); + + context.Reader.ReadEndDocument(); + + try + { + Delegate @delegate = Create.Delegate((MethodInfo)Convert.FromJson(methodName), (Type)Convert.FromJson(targetName)); + if (@delegate == null) + Reflection.Compute.RecordError("Delegate " + methodName + " with target " + targetName + " failed to deserialise."); + return @delegate; + } + catch + { + Reflection.Compute.RecordError("Delegate " + methodName + " with target " + targetName + " failed to deserialise."); + return null; + } + } + + /*******************************************/ + + private IDiscriminatorConvention m_DiscriminatorConvention = BsonSerializer.LookupDiscriminatorConvention(typeof(object)); + } +} diff --git a/Serialiser_Engine/Objects/BsonSerializers/ObjectSerializer.cs b/Serialiser_Engine/Objects/BsonSerializers/ObjectSerializer.cs index 4923ce3e1..a6b477cc8 100644 --- a/Serialiser_Engine/Objects/BsonSerializers/ObjectSerializer.cs +++ b/Serialiser_Engine/Objects/BsonSerializers/ObjectSerializer.cs @@ -193,6 +193,8 @@ private void SerializeDiscriminatedValue(BsonSerializationContext context, BsonS actualType = typeof(Type); else if (value is Enum) actualType = typeof(Enum); + else if (value is Delegate) + actualType = typeof(Delegate); var serializer = BsonSerializer.LookupSerializer(actualType); diff --git a/Serialiser_Engine/Serialiser_Engine.csproj b/Serialiser_Engine/Serialiser_Engine.csproj index 9cb753fee..d24836bb7 100644 --- a/Serialiser_Engine/Serialiser_Engine.csproj +++ b/Serialiser_Engine/Serialiser_Engine.csproj @@ -57,9 +57,11 @@ + + From 9188e17dd9d91ea873e7d2666b1be60a72a99711 Mon Sep 17 00:00:00 2001 From: Eduardo Pignatelli Date: Thu, 8 Aug 2019 15:33:17 +0100 Subject: [PATCH 02/28] start migrating ui methods into reflection namespace --- Data_Engine/Data_Engine.csproj | 1 + Data_Engine/Modify/GroupByName.cs | 80 ++++++++++++++++++ Reflection_Engine/Compute/Compile.cs | 84 +++++++++++++++++++ .../Compute/LoadAllAssemblies.cs | 3 +- Reflection_Engine/Create/MethodInfo.cs | 78 +++++++++++++++++ Reflection_Engine/Modify/MakeGeneric.cs | 75 +++++++++++++++++ Reflection_Engine/Modify/MakeStatic.cs | 69 +++++++++++++++ Reflection_Engine/Query/IsExposed.cs | 78 +++++++++++++++++ Reflection_Engine/Query/MethodList.cs | 22 ++--- Reflection_Engine/Reflection_Engine.csproj | 5 ++ 10 files changed, 479 insertions(+), 16 deletions(-) create mode 100644 Data_Engine/Modify/GroupByName.cs create mode 100644 Reflection_Engine/Compute/Compile.cs create mode 100644 Reflection_Engine/Create/MethodInfo.cs create mode 100644 Reflection_Engine/Modify/MakeGeneric.cs create mode 100644 Reflection_Engine/Modify/MakeStatic.cs create mode 100644 Reflection_Engine/Query/IsExposed.cs diff --git a/Data_Engine/Data_Engine.csproj b/Data_Engine/Data_Engine.csproj index 291b844f6..828ee8a1b 100644 --- a/Data_Engine/Data_Engine.csproj +++ b/Data_Engine/Data_Engine.csproj @@ -73,6 +73,7 @@ + diff --git a/Data_Engine/Modify/GroupByName.cs b/Data_Engine/Modify/GroupByName.cs new file mode 100644 index 000000000..3d522a22b --- /dev/null +++ b/Data_Engine/Modify/GroupByName.cs @@ -0,0 +1,80 @@ +/* + * This file is part of the Buildings and Habitats object Model (BHoM) + * Copyright (c) 2015 - 2018, the respective contributors. All rights reserved. + * + * Each contributor holds copyright over their respective contributions. + * The project versioning (Git) records all such contribution source information. + * + * + * The BHoM is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3.0 of the License, or + * (at your option) any later version. + * + * The BHoM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + */ + +using BH.oM.Data.Collections; +using System.Collections.Generic; +using System.Linq; + +namespace BH.Engine.Data +{ + public static partial class Modify + { + /*************************************/ + /**** Public Methods ****/ + /*************************************/ + + public static Tree GroupByName(this Tree tree) + { + if (tree.Children.Count > 0) + { + if (tree.Children.Values.Any(x => x.Value != null)) + { + var groups = tree.Children.GroupBy(x => + { + int index = x.Key.IndexOf('('); + if (index > 0) + return x.Key.Substring(0, index); + else + return x.Key; + }); + + if (groups.Count() > 1) + { + Dictionary> children = new Dictionary>(); + foreach (var group in groups) + { + if (group.Count() == 1) + { + if (group.First().Value.Value == null) + children.Add(group.Key, group.First().Value); + else + children.Add(group.Key, new Tree { Name = group.Key, Value = group.First().Value.Value }); + } + else + children.Add(group.Key, new Tree { Name = group.Key, Children = group.ToDictionary(x => x.Key, x => x.Value) }); + } + tree.Children = children; + } + } + else + { + foreach (var child in tree.Children.Values) + GroupByName(child); + } + } + + return tree; + } + + /*************************************/ + } +} diff --git a/Reflection_Engine/Compute/Compile.cs b/Reflection_Engine/Compute/Compile.cs new file mode 100644 index 000000000..5513b39f4 --- /dev/null +++ b/Reflection_Engine/Compute/Compile.cs @@ -0,0 +1,84 @@ +/* + * This file is part of the Buildings and Habitats object Model (BHoM) + * Copyright (c) 2015 - 2019, the respective contributors. All rights reserved. + * + * Each contributor holds copyright over their respective contributions. + * The project versioning (Git) records all such contribution source information. + * + * + * The BHoM is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3.0 of the License, or + * (at your option) any later version. + * + * The BHoM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + */ + +using BH.oM.Base; +using BH.oM.Reflection.Debugging; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; + +namespace BH.Engine.Reflection +{ + public static partial class Compute + { + /***************************************************/ + /**** Public Methods ****/ + /***************************************************/ + + public static Delegate Compile(this MethodBase method) + { + if (method is MethodInfo) + return ((MethodInfo)method).Compile(); + else if (method is ConstructorInfo) + return ((ConstructorInfo)method).Compile(); + return null; + } + + /***************************************************/ + + public static Delegate Compile(this MethodInfo method) + { + ParameterExpression lambdaInput = Expression.Parameter(typeof(object[]), "x"); + Expression[] inputs = method.GetParameters().Select((x, i) => Expression.Convert(Expression.ArrayIndex(lambdaInput, Expression.Constant(i)), x.ParameterType)).ToArray(); + + MethodCallExpression methodExpression; + if (method.IsStatic) + { + methodExpression = Expression.Call(method, inputs); + return Expression.Lambda>(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); + return Expression.Lambda>( + Expression.Convert(methodExpression, typeof(object)), + new ParameterExpression[] { instanceParameter, lambdaInput } + ).Compile(); + } + } + + /***************************************************/ + + public static Func Compile(this ConstructorInfo ctor) + { + 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>(Expression.Convert(constructorExpression, typeof(object)), lambdaInput).Compile(); + } + } +} diff --git a/Reflection_Engine/Compute/LoadAllAssemblies.cs b/Reflection_Engine/Compute/LoadAllAssemblies.cs index cf67df5e1..82890a1eb 100644 --- a/Reflection_Engine/Compute/LoadAllAssemblies.cs +++ b/Reflection_Engine/Compute/LoadAllAssemblies.cs @@ -62,8 +62,7 @@ public static void LoadAllAssemblies(string folder = "") continue; } - if (file.EndsWith("oM.dll") || file.EndsWith("_Engine.dll") || file.EndsWith("_Adapter.dll") || - file.EndsWith("_Test.dll") || file.EndsWith("_External.dll")) + if (file.EndsWith("oM.dll") || file.EndsWith("_Engine.dll") || file.EndsWith("_Adapter.dll") || file.EndsWith("_Test.dll")) { try { diff --git a/Reflection_Engine/Create/MethodInfo.cs b/Reflection_Engine/Create/MethodInfo.cs new file mode 100644 index 000000000..c99c23476 --- /dev/null +++ b/Reflection_Engine/Create/MethodInfo.cs @@ -0,0 +1,78 @@ +/* + * This file is part of the Buildings and Habitats object Model (BHoM) + * Copyright (c) 2015 - 2018, the respective contributors. All rights reserved. + * + * Each contributor holds copyright over their respective contributions. + * The project versioning (Git) records all such contribution source information. + * + * + * The BHoM is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3.0 of the License, or + * (at your option) any later version. + * + * The BHoM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + */ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace BH.Engine.Reflection +{ + public static partial class Create + { + /*************************************/ + /**** Public Methods ****/ + /*************************************/ + + public static MethodInfo MethodInfo(this Type declaringType, string methodName, List paramTypes) + { + MethodInfo foundMethod = null; + List 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.MakeGeneric()).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; + } + + /*************************************/ + } +} diff --git a/Reflection_Engine/Modify/MakeGeneric.cs b/Reflection_Engine/Modify/MakeGeneric.cs new file mode 100644 index 000000000..57b4574a6 --- /dev/null +++ b/Reflection_Engine/Modify/MakeGeneric.cs @@ -0,0 +1,75 @@ +/* + * This file is part of the Buildings and Habitats object Model (BHoM) + * Copyright (c) 2015 - 2019, the respective contributors. All rights reserved. + * + * Each contributor holds copyright over their respective contributions. + * The project versioning (Git) records all such contribution source information. + * + * + * The BHoM is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3.0 of the License, or + * (at your option) any later version. + * + * The BHoM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + */ + +using BH.oM.Reflection.Attributes; +using System; +using System.ComponentModel; +using System.Linq; +using System.Reflection; + +namespace BH.Engine.Reflection +{ + public static partial class Modify + { + /***************************************************/ + /**** Public Methods ****/ + /***************************************************/ + + [Description("Returns the specific type from a type that contains generic parameters")] + [Input("genericType", "The generic type. Type is generic if Type.IsGenericParameter or Type.ContrainsGenericparameters is true")] + [Output("type", "The specific type constructed from the generic one")] + public static Type MakeGeneric(this Type genericType) + { + if (genericType.IsGenericParameter) + { + Type[] constrains = genericType.GetGenericParameterConstraints(); + if (constrains.Length == 0) + return typeof(object); + else + return constrains[0]; + } + else if (genericType.ContainsGenericParameters) + { + Type[] constrains = genericType.GetGenericArguments().Select(x => MakeGeneric(x)).ToArray(); + return genericType.GetGenericTypeDefinition().MakeGenericType(constrains); + } + else + return genericType; + } + + /***************************************************/ + + [Description("Returns the specific method from a method that contains generic parameters")] + [Input("genericMethod", "The generic method. Method is generic if MethodInfo.ContainsGenericParameter is true")] + [Output("method", "The specific method constructed from the generic one")] + public static MethodInfo MakeGeneric(this MethodInfo genericMethod) + { + if (genericMethod.ContainsGenericParameters) + { + Type[] types = genericMethod.GetGenericArguments().Select(x => x.MakeGeneric()).ToArray(); + genericMethod = genericMethod.MakeGenericMethod(types); + + } + return genericMethod; + } + } +} \ No newline at end of file diff --git a/Reflection_Engine/Modify/MakeStatic.cs b/Reflection_Engine/Modify/MakeStatic.cs new file mode 100644 index 000000000..d7a883eb7 --- /dev/null +++ b/Reflection_Engine/Modify/MakeStatic.cs @@ -0,0 +1,69 @@ +/* + * This file is part of the Buildings and Habitats object Model (BHoM) + * Copyright (c) 2015 - 2019, the respective contributors. All rights reserved. + * + * Each contributor holds copyright over their respective contributions. + * The project versioning (Git) records all such contribution source information. + * + * + * The BHoM is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3.0 of the License, or + * (at your option) any later version. + * + * The BHoM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + */ + +using BH.oM.Reflection.Attributes; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; + +namespace BH.Engine.Reflection +{ + public static partial class Modify + { + /***************************************************/ + /**** Public Methods ****/ + /***************************************************/ + + [Description("Returns the specific type from a type that contains generic parameters")] + [Input("genericType", "The generic type")] + [Output("type", "The specific type constructed from the generic one")] + public static MethodInfo MakeStatic(this MethodInfo method) + { + if (method == null) + return null; + + ParameterInfo[] parameters = method.GetParameters(); + + List parameterTypes = parameters.Select(x => x.ParameterType).ToList(); + parameterTypes.Add(method.ReturnType); + if (!method.IsStatic) + parameterTypes.Insert(0, method.DeclaringType); + + object firstArgument = method.IsStatic ? null : method.DeclaringType; + + if (method.IsGenericMethod || method.ContainsGenericParameters) + return null; + //method = method.ConstructGeneric(); + + Type delegateType = Expression.GetDelegateType(parameterTypes.ToArray()); + Delegate @delegate = Delegate.CreateDelegate(delegateType, method); + + + return @delegate.Method; + } + + /***************************************************/ + } +} \ No newline at end of file diff --git a/Reflection_Engine/Query/IsExposed.cs b/Reflection_Engine/Query/IsExposed.cs new file mode 100644 index 000000000..d8f465a61 --- /dev/null +++ b/Reflection_Engine/Query/IsExposed.cs @@ -0,0 +1,78 @@ +/* + * This file is part of the Buildings and Habitats object Model (BHoM) + * Copyright (c) 2015 - 2018, the respective contributors. All rights reserved. + * + * Each contributor holds copyright over their respective contributions. + * The project versioning (Git) records all such contribution source information. + * + * + * The BHoM is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3.0 of the License, or + * (at your option) any later version. + * + * The BHoM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + */ + +using System; +using System.Reflection; + +namespace BH.Engine.Reflection +{ + public static partial class Query + { + /***************************************************/ + /**** Public Methods - Interfaces ****/ + /***************************************************/ + + public static bool IIsExposed(this object obj) + { + if (obj == null) + return false; + else + return IsExposed(obj as dynamic); + } + + + /***************************************************/ + /**** Public Methods ****/ + /***************************************************/ + + public static bool IsExposed(this MethodBase method) + { + return !method.IsNotImplemented() && !method.IsDeprecated(); + } + + /***************************************************/ + + public static bool IsExposed(this Type type) + { + return !type.IsNotImplemented() && !type.IsDeprecated(); + } + + /***************************************************/ + + public static bool IsExposed(this Delegate @delegate) + { + return @delegate != null; + } + + + /***************************************************/ + /**** Private Methods - Fallback case ****/ + /***************************************************/ + + private static bool IsExposed(this object obj) + { + return true; + } + + /***************************************************/ + } +} diff --git a/Reflection_Engine/Query/MethodList.cs b/Reflection_Engine/Query/MethodList.cs index 076ea5089..317c58f4f 100644 --- a/Reflection_Engine/Query/MethodList.cs +++ b/Reflection_Engine/Query/MethodList.cs @@ -61,7 +61,7 @@ public static List AllMethodList() /***************************************************/ - public static List ExternalMethodList() + public static List ExternalMethodList() { // If the dictionary exists already return it if (m_ExternamMethodList == null || m_ExternamMethodList.Count <= 0) @@ -103,7 +103,12 @@ private static void ExtractAllMethods() if (type.Name == "External") { - + List methods = type.GetMethod("ExternalMethods")?.Invoke(null, null) as List; + if (methods != null && methods.Count > 0) + { + m_ExternamMethodList.AddRange(methods); + //m_BHoMMethodList.AddRange(methods); + } } // Get everything StoreAllMethods(type); @@ -116,17 +121,6 @@ private static void ExtractAllMethods() StoreAllMethods(type); } } - else if (name.EndsWith("_External")) - { - foreach (Type type in asm.GetTypes()) - { - if (type is BHoMAddin) - (BHoMAddin)type).ExternalMethods(); - List externalDelegates = type.GetMethod("ExternalMethods")?.Invoke(null, null) as List; - if (externalDelegates != null) - m_ExternamMethodList.AddRange(externalDelegates); - } - } } catch (Exception) { @@ -154,7 +148,7 @@ private static void StoreAllMethods(Type type) private static List m_BHoMMethodList = new List(); private static List m_AllMethodList = new List(); - private static List m_ExternamMethodList = new List(); + private static List m_ExternamMethodList = new List(); /***************************************************/ } diff --git a/Reflection_Engine/Reflection_Engine.csproj b/Reflection_Engine/Reflection_Engine.csproj index 7ce151c6b..a10455b73 100644 --- a/Reflection_Engine/Reflection_Engine.csproj +++ b/Reflection_Engine/Reflection_Engine.csproj @@ -88,19 +88,24 @@ + + + + + From fe70cce2019e4125d7849609bdc04c2f1ccf5b42 Mon Sep 17 00:00:00 2001 From: Eduardo Pignatelli Date: Thu, 8 Aug 2019 16:39:33 +0100 Subject: [PATCH 03/28] don't know how to deal with generic methods yet - return null for now --- Reflection_Engine/Modify/MakeStatic.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Reflection_Engine/Modify/MakeStatic.cs b/Reflection_Engine/Modify/MakeStatic.cs index d7a883eb7..567d0ddfb 100644 --- a/Reflection_Engine/Modify/MakeStatic.cs +++ b/Reflection_Engine/Modify/MakeStatic.cs @@ -54,13 +54,11 @@ public static MethodInfo MakeStatic(this MethodInfo method) object firstArgument = method.IsStatic ? null : method.DeclaringType; if (method.IsGenericMethod || method.ContainsGenericParameters) - return null; - //method = method.ConstructGeneric(); + return null; //method = method.ConstructGeneric(); Type delegateType = Expression.GetDelegateType(parameterTypes.ToArray()); Delegate @delegate = Delegate.CreateDelegate(delegateType, method); - return @delegate.Method; } From 63ac9a9c7812f6953680ddca1d51d5f825d195d5 Mon Sep 17 00:00:00 2001 From: Eduardo Pignatelli Date: Thu, 8 Aug 2019 17:26:37 +0100 Subject: [PATCH 04/28] clean tree --- Data_Engine/Create/Tree.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Data_Engine/Create/Tree.cs b/Data_Engine/Create/Tree.cs index 1bcab932c..81c482235 100644 --- a/Data_Engine/Create/Tree.cs +++ b/Data_Engine/Create/Tree.cs @@ -23,6 +23,7 @@ using BH.oM.Data.Collections; using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; namespace BH.Engine.Data { @@ -78,8 +79,6 @@ public static Tree Tree(List items, List> paths, string na return tree; } - - /***************************************************/ } } From 94a65b4bb620e09b2ba16dffff3920592444e3da Mon Sep 17 00:00:00 2001 From: Eduardo Pignatelli Date: Fri, 9 Aug 2019 10:54:49 +0100 Subject: [PATCH 05/28] MakeStatic is now WIP --- Reflection_Engine/Modify/MakeStatic.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Reflection_Engine/Modify/MakeStatic.cs b/Reflection_Engine/Modify/MakeStatic.cs index 567d0ddfb..ff82c3869 100644 --- a/Reflection_Engine/Modify/MakeStatic.cs +++ b/Reflection_Engine/Modify/MakeStatic.cs @@ -37,10 +37,13 @@ public static partial class Modify /***************************************************/ [Description("Returns the specific type from a type that contains generic parameters")] - [Input("genericType", "The generic type")] + [Input("method", "The generic type")] [Output("type", "The specific type constructed from the generic one")] public static MethodInfo MakeStatic(this MethodInfo method) { + // This is not really true, the method will not be static after processing. + // This has to be fixed + if (method == null) return null; @@ -54,7 +57,7 @@ public static MethodInfo MakeStatic(this MethodInfo method) object firstArgument = method.IsStatic ? null : method.DeclaringType; if (method.IsGenericMethod || method.ContainsGenericParameters) - return null; //method = method.ConstructGeneric(); + return null; //method = method.MakeGeneric(); Type delegateType = Expression.GetDelegateType(parameterTypes.ToArray()); Delegate @delegate = Delegate.CreateDelegate(delegateType, method); From e1565ba184b0e9d18b3115245b2d4e383353d66b Mon Sep 17 00:00:00 2001 From: Eduardo Pignatelli Date: Fri, 9 Aug 2019 10:55:28 +0100 Subject: [PATCH 06/28] Move Create.MethodBase to the Reflection_Engine --- .../Create/MethodBase.cs | 20 ++++++++++++++----- Reflection_Engine/Reflection_Engine.csproj | 1 + Serialiser_Engine/Serialiser_Engine.csproj | 1 - 3 files changed, 16 insertions(+), 6 deletions(-) rename {Serialiser_Engine => Reflection_Engine}/Create/MethodBase.cs (81%) diff --git a/Serialiser_Engine/Create/MethodBase.cs b/Reflection_Engine/Create/MethodBase.cs similarity index 81% rename from Serialiser_Engine/Create/MethodBase.cs rename to Reflection_Engine/Create/MethodBase.cs index 5bb92c81d..4af13e36b 100644 --- a/Serialiser_Engine/Create/MethodBase.cs +++ b/Reflection_Engine/Create/MethodBase.cs @@ -33,7 +33,7 @@ public static partial class Create /**** Public Methods ****/ /*******************************************/ - public static MethodBase MethodBase(Type type, string methodName, List paramTypes) + public static MethodBase MethodBase(Type type, string methodName, List paramTypesJson) { List methods; if (methodName == ".ctor") @@ -48,12 +48,12 @@ public static MethodBase MethodBase(Type type, string methodName, List p if (method.Name == methodName) { ParameterInfo[] parameters = method.ParametersWithConstraints(); - if (parameters.Length == paramTypes.Count) + if (parameters.Length == paramTypesJson.Count) { bool matching = true; - List names = parameters.Select(x => Convert.ToJson(x.ParameterType)).ToList(); - for (int i = 0; i < paramTypes.Count; i++) - matching &= names[i] == paramTypes[i]; + List names = parameters.Select(x => x.ParameterType.Name).ToList(); + for (int i = 0; i < paramTypesJson.Count; i++) + matching &= names[i] == paramTypesJson[i]; if (matching) { @@ -66,5 +66,15 @@ public static MethodBase MethodBase(Type type, string methodName, List p } /*******************************************/ + + public static MethodBase MethodBase(Type type, string methodName, List paramTypes) + { + if (methodName == ".ctor") + return type.GetConstructor(paramTypes.ToArray()); + else + return type.GetMethod(methodName, paramTypes.ToArray()); + } + + /*******************************************/ } } diff --git a/Reflection_Engine/Reflection_Engine.csproj b/Reflection_Engine/Reflection_Engine.csproj index a10455b73..b8f7ea85c 100644 --- a/Reflection_Engine/Reflection_Engine.csproj +++ b/Reflection_Engine/Reflection_Engine.csproj @@ -95,6 +95,7 @@ + diff --git a/Serialiser_Engine/Serialiser_Engine.csproj b/Serialiser_Engine/Serialiser_Engine.csproj index d24836bb7..a72c49fd6 100644 --- a/Serialiser_Engine/Serialiser_Engine.csproj +++ b/Serialiser_Engine/Serialiser_Engine.csproj @@ -58,7 +58,6 @@ - From ddbd5e6f64ed712e44c23bbbcf85c2c79a61dd74 Mon Sep 17 00:00:00 2001 From: Eduardo Pignatelli Date: Fri, 9 Aug 2019 10:56:04 +0100 Subject: [PATCH 07/28] Move Query.GenericTypeContraint to the Reflection_Engine --- .../Query/GenericTypeConstraint.cs | 0 Reflection_Engine/Reflection_Engine.csproj | 1 + Serialiser_Engine/Serialiser_Engine.csproj | 1 - 3 files changed, 1 insertion(+), 1 deletion(-) rename {Serialiser_Engine => Reflection_Engine}/Query/GenericTypeConstraint.cs (100%) diff --git a/Serialiser_Engine/Query/GenericTypeConstraint.cs b/Reflection_Engine/Query/GenericTypeConstraint.cs similarity index 100% rename from Serialiser_Engine/Query/GenericTypeConstraint.cs rename to Reflection_Engine/Query/GenericTypeConstraint.cs diff --git a/Reflection_Engine/Reflection_Engine.csproj b/Reflection_Engine/Reflection_Engine.csproj index b8f7ea85c..289b88331 100644 --- a/Reflection_Engine/Reflection_Engine.csproj +++ b/Reflection_Engine/Reflection_Engine.csproj @@ -104,6 +104,7 @@ + diff --git a/Serialiser_Engine/Serialiser_Engine.csproj b/Serialiser_Engine/Serialiser_Engine.csproj index a72c49fd6..b4322c898 100644 --- a/Serialiser_Engine/Serialiser_Engine.csproj +++ b/Serialiser_Engine/Serialiser_Engine.csproj @@ -73,7 +73,6 @@ - From 598a2b87a581dc7706a326d179f9289e345db0f3 Mon Sep 17 00:00:00 2001 From: Eduardo Pignatelli Date: Fri, 9 Aug 2019 10:56:49 +0100 Subject: [PATCH 08/28] Move Query.ParameterWithConstraints to the Reflection_Engine --- .../Query/ParametersWithConstraints.cs | 0 Reflection_Engine/Reflection_Engine.csproj | 1 + Serialiser_Engine/Serialiser_Engine.csproj | 1 - 3 files changed, 1 insertion(+), 1 deletion(-) rename {Serialiser_Engine => Reflection_Engine}/Query/ParametersWithConstraints.cs (100%) diff --git a/Serialiser_Engine/Query/ParametersWithConstraints.cs b/Reflection_Engine/Query/ParametersWithConstraints.cs similarity index 100% rename from Serialiser_Engine/Query/ParametersWithConstraints.cs rename to Reflection_Engine/Query/ParametersWithConstraints.cs diff --git a/Reflection_Engine/Reflection_Engine.csproj b/Reflection_Engine/Reflection_Engine.csproj index 289b88331..0c762238c 100644 --- a/Reflection_Engine/Reflection_Engine.csproj +++ b/Reflection_Engine/Reflection_Engine.csproj @@ -119,6 +119,7 @@ + diff --git a/Serialiser_Engine/Serialiser_Engine.csproj b/Serialiser_Engine/Serialiser_Engine.csproj index b4322c898..b3d346b54 100644 --- a/Serialiser_Engine/Serialiser_Engine.csproj +++ b/Serialiser_Engine/Serialiser_Engine.csproj @@ -73,7 +73,6 @@ - From 0222033f6bcbbaac1f3b7f5204ab4d8301b26cf4 Mon Sep 17 00:00:00 2001 From: Eduardo Pignatelli Date: Fri, 9 Aug 2019 10:57:29 +0100 Subject: [PATCH 09/28] Remove serialisation of Delegates --- Serialiser_Engine/Convert/Bson.cs | 1 - Serialiser_Engine/Create/Delegate.cs | 65 ----------- .../BsonSerializers/DelegateSerializser.cs | 104 ------------------ Serialiser_Engine/Serialiser_Engine.csproj | 2 - 4 files changed, 172 deletions(-) delete mode 100644 Serialiser_Engine/Create/Delegate.cs delete mode 100644 Serialiser_Engine/Objects/BsonSerializers/DelegateSerializser.cs diff --git a/Serialiser_Engine/Convert/Bson.cs b/Serialiser_Engine/Convert/Bson.cs index e2e0e4a5f..92e03eb36 100644 --- a/Serialiser_Engine/Convert/Bson.cs +++ b/Serialiser_Engine/Convert/Bson.cs @@ -125,7 +125,6 @@ private static void RegisterTypes() BsonSerializer.RegisterSerializer(typeof(object), new BH_ObjectSerializer()); BsonSerializer.RegisterSerializer(typeof(System.Drawing.Color), new ColourSerializer()); BsonSerializer.RegisterSerializer(typeof(MethodBase), new MethodBaseSerializer()); - BsonSerializer.RegisterSerializer(typeof(Delegate), new DelegateSerializer()); BsonSerializer.RegisterSerializer(typeof(Guid), new GuidSerializer(BsonType.String)); BsonSerializer.RegisterSerializer(typeof(CustomObject), new CustomObjectSerializer()); BsonSerializer.RegisterSerializer(typeof(Enum), new EnumSerializer()); diff --git a/Serialiser_Engine/Create/Delegate.cs b/Serialiser_Engine/Create/Delegate.cs deleted file mode 100644 index 703f22841..000000000 --- a/Serialiser_Engine/Create/Delegate.cs +++ /dev/null @@ -1,65 +0,0 @@ -/* - * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2018, the respective contributors. All rights reserved. - * - * Each contributor holds copyright over their respective contributions. - * The project versioning (Git) records all such contribution source information. - * - * - * The BHoM is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3.0 of the License, or - * (at your option) any later version. - * - * The BHoM is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this code. If not, see . - */ - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Linq.Expressions; -using System.Reflection; - -namespace BH.Engine.Serialiser -{ - public static partial class Create - { - /*******************************************/ - /**** Public Methods ****/ - /*******************************************/ - - public static Delegate Delegate(this MethodInfo method, Type target) - { - ParameterInfo[] parameters = method.GetParameters(); - - List parameterTypes = parameters.Select(x => x.ParameterType).ToList(); - parameterTypes.Add(method.ReturnType); - if (!method.IsStatic) - parameterTypes.Insert(0, target); - - object firstArgument = method.IsStatic ? null : target ?? method.DeclaringType; - - if (method.IsGenericMethod || method.ContainsGenericParameters) - { - //Type[] types = method.GetGenericArguments().Select(x => GetConstructedType(x)).ToArray(); - //method = method.MakeGenericMethod(types); - //return method; - return null; - } - - Type delegateType = Expression.GetDelegateType(parameterTypes.ToArray()); - Delegate @delegate = System.Delegate.CreateDelegate(delegateType, method); - - - return @delegate; - } - - /*******************************************/ - } -} diff --git a/Serialiser_Engine/Objects/BsonSerializers/DelegateSerializser.cs b/Serialiser_Engine/Objects/BsonSerializers/DelegateSerializser.cs deleted file mode 100644 index 3066b4bdd..000000000 --- a/Serialiser_Engine/Objects/BsonSerializers/DelegateSerializser.cs +++ /dev/null @@ -1,104 +0,0 @@ -/* - * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2018, the respective contributors. All rights reserved. - * - * Each contributor holds copyright over their respective contributions. - * The project versioning (Git) records all such contribution source information. - * - * - * The BHoM is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3.0 of the License, or - * (at your option) any later version. - * - * The BHoM is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this code. If not, see . - */ - -using MongoDB.Bson; -using MongoDB.Bson.IO; -using MongoDB.Bson.Serialization; -using MongoDB.Bson.Serialization.Conventions; -using MongoDB.Bson.Serialization.Serializers; -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Linq; -using System.Reflection; - -namespace BH.Engine.Serialiser.BsonSerializers -{ - public class DelegateSerializer : SerializerBase, IBsonPolymorphicSerializer - { - /*******************************************/ - /**** Properties ****/ - /*******************************************/ - - public bool IsDiscriminatorCompatibleWithObjectSerializer { get; } = true; - - - /*******************************************/ - /**** Public Methods ****/ - /*******************************************/ - - public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, Delegate value) - { - var bsonWriter = context.Writer; - bsonWriter.WriteStartDocument(); - - var discriminator = m_DiscriminatorConvention.GetDiscriminator(typeof(object), typeof(Delegate)); - bsonWriter.WriteName(m_DiscriminatorConvention.ElementName); - BsonValueSerializer.Instance.Serialize(context, discriminator); - - bsonWriter.WriteName("Method"); - bsonWriter.WriteString(value.Method.ToJson()); - - bsonWriter.WriteName("Target"); - bsonWriter.WriteString(value.Target?.ToJson() ?? ""); - - bsonWriter.WriteEndDocument(); - } - - /*******************************************/ - - public override Delegate Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) - { - var bsonReader = context.Reader; - bsonReader.ReadStartDocument(); - - string text = bsonReader.ReadName(); - if (text == m_DiscriminatorConvention.ElementName) - bsonReader.SkipValue(); - - bsonReader.ReadName(); - string methodName = bsonReader.ReadString(); - - bsonReader.ReadName(); - string targetName = bsonReader.ReadString(); - - context.Reader.ReadEndDocument(); - - try - { - Delegate @delegate = Create.Delegate((MethodInfo)Convert.FromJson(methodName), (Type)Convert.FromJson(targetName)); - if (@delegate == null) - Reflection.Compute.RecordError("Delegate " + methodName + " with target " + targetName + " failed to deserialise."); - return @delegate; - } - catch - { - Reflection.Compute.RecordError("Delegate " + methodName + " with target " + targetName + " failed to deserialise."); - return null; - } - } - - /*******************************************/ - - private IDiscriminatorConvention m_DiscriminatorConvention = BsonSerializer.LookupDiscriminatorConvention(typeof(object)); - } -} diff --git a/Serialiser_Engine/Serialiser_Engine.csproj b/Serialiser_Engine/Serialiser_Engine.csproj index b3d346b54..b042a22aa 100644 --- a/Serialiser_Engine/Serialiser_Engine.csproj +++ b/Serialiser_Engine/Serialiser_Engine.csproj @@ -57,10 +57,8 @@ - - From d3b83164b5d549ee9ff253315ce4281139bd7f91 Mon Sep 17 00:00:00 2001 From: Eduardo Pignatelli Date: Fri, 9 Aug 2019 10:57:46 +0100 Subject: [PATCH 10/28] Fix Deserialisation of MethodBase --- .../Objects/BsonSerializers/MethodBaseSerializer.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Serialiser_Engine/Objects/BsonSerializers/MethodBaseSerializer.cs b/Serialiser_Engine/Objects/BsonSerializers/MethodBaseSerializer.cs index 8622b186b..5937a2b70 100644 --- a/Serialiser_Engine/Objects/BsonSerializers/MethodBaseSerializer.cs +++ b/Serialiser_Engine/Objects/BsonSerializers/MethodBaseSerializer.cs @@ -88,18 +88,20 @@ public override MethodBase Deserialize(BsonDeserializationContext context, BsonD bsonReader.ReadName(); string methodName = bsonReader.ReadString(); - List paramTypes = new List(); + List paramTypesJson = new List(); bsonReader.ReadName(); bsonReader.ReadStartArray(); while (bsonReader.ReadBsonType() != BsonType.EndOfDocument) - paramTypes.Add(bsonReader.ReadString()); + paramTypesJson.Add(bsonReader.ReadString()); bsonReader.ReadEndArray(); context.Reader.ReadEndDocument(); try { - MethodBase method = Create.MethodBase((Type)Convert.FromJson(typeName), methodName, paramTypes); + List types = paramTypesJson.Select(x => Convert.FromJson(x)).Cast().ToList(); + MethodBase method = Create.MethodBase((Type)Convert.FromJson(typeName), methodName, types); // type overload + if (method == null) Reflection.Compute.RecordError("Method " + methodName + " from " + typeName + " failed to deserialise."); return method; From 7df300d2487dd5cd3a5f438fb907f35a6f096519 Mon Sep 17 00:00:00 2001 From: Eduardo Pignatelli Date: Mon, 12 Aug 2019 10:53:18 +0100 Subject: [PATCH 11/28] Fix association of components with back-end methods that return void --- Reflection_Engine/Compute/Compile.cs | 28 +++++++++++++++++--------- Reflection_Engine/Create/MethodBase.cs | 14 +++++++++++-- 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/Reflection_Engine/Compute/Compile.cs b/Reflection_Engine/Compute/Compile.cs index 5513b39f4..77ec6d6e0 100644 --- a/Reflection_Engine/Compute/Compile.cs +++ b/Reflection_Engine/Compute/Compile.cs @@ -20,11 +20,7 @@ * along with this code. If not, see . */ -using BH.oM.Base; -using BH.oM.Reflection.Debugging; using System; -using System.Collections; -using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Reflection; @@ -57,17 +53,31 @@ public static Delegate Compile(this MethodInfo method) if (method.IsStatic) { methodExpression = Expression.Call(method, inputs); - return Expression.Lambda>(Expression.Convert(methodExpression, typeof(object)), lambdaInput).Compile(); + if (method.ReturnType == typeof(void)) + return Expression.Lambda>(Expression.Convert(methodExpression, typeof(void)), lambdaInput).Compile(); + else + return Expression.Lambda>(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); - return Expression.Lambda>( - Expression.Convert(methodExpression, typeof(object)), - new ParameterExpression[] { instanceParameter, lambdaInput } - ).Compile(); + + if (method.ReturnType == typeof(void)) + { + return Expression.Lambda>( + Expression.Convert(methodExpression, typeof(void)), + new ParameterExpression[] { instanceParameter, lambdaInput } + ).Compile(); + } + else + { + return Expression.Lambda>( + Expression.Convert(methodExpression, typeof(object)), + new ParameterExpression[] { instanceParameter, lambdaInput } + ).Compile(); + } } } diff --git a/Reflection_Engine/Create/MethodBase.cs b/Reflection_Engine/Create/MethodBase.cs index 4af13e36b..74828daf5 100644 --- a/Reflection_Engine/Create/MethodBase.cs +++ b/Reflection_Engine/Create/MethodBase.cs @@ -69,10 +69,20 @@ public static MethodBase MethodBase(Type type, string methodName, List p public static MethodBase MethodBase(Type type, string methodName, List paramTypes) { + MethodBase method; if (methodName == ".ctor") - return type.GetConstructor(paramTypes.ToArray()); + method = type.GetConstructor(paramTypes.ToArray()); else - return type.GetMethod(methodName, paramTypes.ToArray()); + method = type.GetMethod(methodName, paramTypes.ToArray()); + + // the above will return null if the type is a generic type + // that is because we serialise a generic method with its constraints + // rather than serialising the generics + if (method != null) + return method; + + // So, let's try the other overload + return MethodBase(type, methodName, paramTypes.Select(x => x.Name).ToList()); } /*******************************************/ From 49368925c63f1c85a69eb898ad1404392f267025 Mon Sep 17 00:00:00 2001 From: Eduardo Pignatelli Date: Tue, 13 Aug 2019 10:37:40 +0100 Subject: [PATCH 12/28] improve readability for parameter in Engine.Reflection.Create.MethodBase --- Reflection_Engine/Create/MethodBase.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Reflection_Engine/Create/MethodBase.cs b/Reflection_Engine/Create/MethodBase.cs index 74828daf5..8f23731aa 100644 --- a/Reflection_Engine/Create/MethodBase.cs +++ b/Reflection_Engine/Create/MethodBase.cs @@ -33,7 +33,7 @@ public static partial class Create /**** Public Methods ****/ /*******************************************/ - public static MethodBase MethodBase(Type type, string methodName, List paramTypesJson) + public static MethodBase MethodBase(Type type, string methodName, List paramTypeNames) { List methods; if (methodName == ".ctor") @@ -48,12 +48,12 @@ public static MethodBase MethodBase(Type type, string methodName, List p if (method.Name == methodName) { ParameterInfo[] parameters = method.ParametersWithConstraints(); - if (parameters.Length == paramTypesJson.Count) + if (parameters.Length == paramTypeNames.Count) { bool matching = true; List names = parameters.Select(x => x.ParameterType.Name).ToList(); - for (int i = 0; i < paramTypesJson.Count; i++) - matching &= names[i] == paramTypesJson[i]; + for (int i = 0; i < paramTypeNames.Count; i++) + matching &= names[i] == paramTypeNames[i]; if (matching) { From 4b55f13e0eac9d5d00a4da3154f610319476a664 Mon Sep 17 00:00:00 2001 From: Eduardo Pignatelli Date: Tue, 13 Aug 2019 10:43:19 +0100 Subject: [PATCH 13/28] Rename Compute.Compile to Create.Delegate --- .../{Compute/Compile.cs => Create/Delegate.cs} | 8 ++++---- Reflection_Engine/Reflection_Engine.csproj | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) rename Reflection_Engine/{Compute/Compile.cs => Create/Delegate.cs} (94%) diff --git a/Reflection_Engine/Compute/Compile.cs b/Reflection_Engine/Create/Delegate.cs similarity index 94% rename from Reflection_Engine/Compute/Compile.cs rename to Reflection_Engine/Create/Delegate.cs index 77ec6d6e0..1ab6c3112 100644 --- a/Reflection_Engine/Compute/Compile.cs +++ b/Reflection_Engine/Create/Delegate.cs @@ -27,13 +27,13 @@ namespace BH.Engine.Reflection { - public static partial class Compute + public static partial class Create { /***************************************************/ /**** Public Methods ****/ /***************************************************/ - public static Delegate Compile(this MethodBase method) + public static Delegate Delegate(this MethodBase method) { if (method is MethodInfo) return ((MethodInfo)method).Compile(); @@ -44,7 +44,7 @@ public static Delegate Compile(this MethodBase method) /***************************************************/ - public static Delegate Compile(this MethodInfo method) + public static Delegate Delegate(this MethodInfo method) { ParameterExpression lambdaInput = Expression.Parameter(typeof(object[]), "x"); Expression[] inputs = method.GetParameters().Select((x, i) => Expression.Convert(Expression.ArrayIndex(lambdaInput, Expression.Constant(i)), x.ParameterType)).ToArray(); @@ -83,7 +83,7 @@ public static Delegate Compile(this MethodInfo method) /***************************************************/ - public static Func Compile(this ConstructorInfo ctor) + public static Func Delegate(this ConstructorInfo ctor) { 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(); diff --git a/Reflection_Engine/Reflection_Engine.csproj b/Reflection_Engine/Reflection_Engine.csproj index 0c762238c..2eac4cce4 100644 --- a/Reflection_Engine/Reflection_Engine.csproj +++ b/Reflection_Engine/Reflection_Engine.csproj @@ -88,13 +88,13 @@ - + From ee037bcec93b96e2c24c6f0e3e94119b095d4b5f Mon Sep 17 00:00:00 2001 From: Eduardo Pignatelli Date: Tue, 13 Aug 2019 10:43:51 +0100 Subject: [PATCH 14/28] replace instances --- Reflection_Engine/Create/Delegate.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Reflection_Engine/Create/Delegate.cs b/Reflection_Engine/Create/Delegate.cs index 1ab6c3112..9b223a583 100644 --- a/Reflection_Engine/Create/Delegate.cs +++ b/Reflection_Engine/Create/Delegate.cs @@ -36,9 +36,9 @@ public static partial class Create public static Delegate Delegate(this MethodBase method) { if (method is MethodInfo) - return ((MethodInfo)method).Compile(); + return ((MethodInfo)method).Delegate(); else if (method is ConstructorInfo) - return ((ConstructorInfo)method).Compile(); + return ((ConstructorInfo)method).Delegate(); return null; } From 3841f34144b018ad745f19792c9780e357bad83a Mon Sep 17 00:00:00 2001 From: Eduardo Pignatelli Date: Tue, 13 Aug 2019 11:42:19 +0100 Subject: [PATCH 15/28] Rally all cross-cases of isntance method and methods returning void under one delegate type `Func` --- .../{Create/Delegate.cs => Convert/ToFunc.cs} | 42 +++++++++++++++---- Reflection_Engine/Reflection_Engine.csproj | 2 +- 2 files changed, 34 insertions(+), 10 deletions(-) rename Reflection_Engine/{Create/Delegate.cs => Convert/ToFunc.cs} (77%) diff --git a/Reflection_Engine/Create/Delegate.cs b/Reflection_Engine/Convert/ToFunc.cs similarity index 77% rename from Reflection_Engine/Create/Delegate.cs rename to Reflection_Engine/Convert/ToFunc.cs index 9b223a583..334233af8 100644 --- a/Reflection_Engine/Create/Delegate.cs +++ b/Reflection_Engine/Convert/ToFunc.cs @@ -27,24 +27,25 @@ namespace BH.Engine.Reflection { - public static partial class Create + public static partial class Convert { /***************************************************/ /**** Public Methods ****/ /***************************************************/ - public static Delegate Delegate(this MethodBase method) + + public static Func ToFunc(this MethodBase method) { if (method is MethodInfo) - return ((MethodInfo)method).Delegate(); + return ((MethodInfo)method).ToFunc(); else if (method is ConstructorInfo) - return ((ConstructorInfo)method).Delegate(); + return ((ConstructorInfo)method).ToFunc(); return null; } /***************************************************/ - public static Delegate Delegate(this MethodInfo method) + public static Func ToFunc(this MethodInfo method) { ParameterExpression lambdaInput = Expression.Parameter(typeof(object[]), "x"); Expression[] inputs = method.GetParameters().Select((x, i) => Expression.Convert(Expression.ArrayIndex(lambdaInput, Expression.Constant(i)), x.ParameterType)).ToArray(); @@ -54,7 +55,7 @@ public static Delegate Delegate(this MethodInfo method) { methodExpression = Expression.Call(method, inputs); if (method.ReturnType == typeof(void)) - return Expression.Lambda>(Expression.Convert(methodExpression, typeof(void)), lambdaInput).Compile(); + return Expression.Lambda>(Expression.Convert(methodExpression, typeof(void)), lambdaInput).Compile().ToFunc(); else return Expression.Lambda>(Expression.Convert(methodExpression, typeof(object)), lambdaInput).Compile(); } @@ -69,26 +70,49 @@ public static Delegate Delegate(this MethodInfo method) return Expression.Lambda>( Expression.Convert(methodExpression, typeof(void)), new ParameterExpression[] { instanceParameter, lambdaInput } - ).Compile(); + ).Compile().ToFunc(); } else { return Expression.Lambda>( Expression.Convert(methodExpression, typeof(object)), new ParameterExpression[] { instanceParameter, lambdaInput } - ).Compile(); + ).Compile().ToFunc(); } } } /***************************************************/ - public static Func Delegate(this ConstructorInfo ctor) + public static Func ToFunc(this ConstructorInfo ctor) { 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>(Expression.Convert(constructorExpression, typeof(object)), lambdaInput).Compile(); } + + /***************************************************/ + + public static Func ToFunc(this Action act) + { + return inputs => { act(inputs); return true; }; + } + + /***************************************************/ + + public static Func ToFunc(this Func func) + { + return inputs => { return func(inputs[0], inputs); }; + } + + /***************************************************/ + + public static Func ToFunc(this Action act) + { + return inputs => { act(inputs[0], inputs); return true; }; + } + + /***************************************************/ } } diff --git a/Reflection_Engine/Reflection_Engine.csproj b/Reflection_Engine/Reflection_Engine.csproj index 2eac4cce4..b40f6551c 100644 --- a/Reflection_Engine/Reflection_Engine.csproj +++ b/Reflection_Engine/Reflection_Engine.csproj @@ -93,8 +93,8 @@ + - From 5a16b109533e3821df05d0bf3ebb85af909ec8f9 Mon Sep 17 00:00:00 2001 From: Eduardo Pignatelli Date: Tue, 13 Aug 2019 11:46:57 +0100 Subject: [PATCH 16/28] Move method to collected methods in nested types from Numpy_Toolkit --- Reflection_Engine/Query/NestedMethods.cs | 52 ++++++++++++++++++++++ Reflection_Engine/Reflection_Engine.csproj | 1 + 2 files changed, 53 insertions(+) create mode 100644 Reflection_Engine/Query/NestedMethods.cs diff --git a/Reflection_Engine/Query/NestedMethods.cs b/Reflection_Engine/Query/NestedMethods.cs new file mode 100644 index 000000000..ca923fbde --- /dev/null +++ b/Reflection_Engine/Query/NestedMethods.cs @@ -0,0 +1,52 @@ +/* + * This file is part of the Buildings and Habitats object Model (BHoM) + * Copyright (c) 2015 - 2019, the respective contributors. All rights reserved. + * + * Each contributor holds copyright over their respective contributions. + * The project versioning (Git) records all such contribution source information. + * + * + * The BHoM is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3.0 of the License, or + * (at your option) any later version. + * + * The BHoM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + */ + +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Linq; + +namespace BH.Engine.Reflection +{ + public static partial class Query + { + /***************************************************/ + /**** Public Methods ****/ + /***************************************************/ + + public static List GetAllMethods(this Type type) + { + List methods = type.GetMethods().ToList(); + Type[] nestedTypes = type.GetNestedTypes(); + + while (nestedTypes.Length > 0) + { + methods.Concat(nestedTypes.SelectMany(x => x.GetMethods())); + nestedTypes = nestedTypes.SelectMany(x => x.GetNestedTypes()).ToArray(); + } + + return methods; + } + + /***************************************************/ + } +} diff --git a/Reflection_Engine/Reflection_Engine.csproj b/Reflection_Engine/Reflection_Engine.csproj index b40f6551c..c544053fa 100644 --- a/Reflection_Engine/Reflection_Engine.csproj +++ b/Reflection_Engine/Reflection_Engine.csproj @@ -109,6 +109,7 @@ + From cfbf766e73fdfc0399721553dd707ebded67f453 Mon Sep 17 00:00:00 2001 From: Eduardo Pignatelli Date: Tue, 13 Aug 2019 12:09:33 +0100 Subject: [PATCH 17/28] files doesn't require this change --- Data_Engine/Create/Tree.cs | 1 - Serialiser_Engine/Objects/BsonSerializers/ObjectSerializer.cs | 2 -- 2 files changed, 3 deletions(-) diff --git a/Data_Engine/Create/Tree.cs b/Data_Engine/Create/Tree.cs index 81c482235..c03b6a448 100644 --- a/Data_Engine/Create/Tree.cs +++ b/Data_Engine/Create/Tree.cs @@ -23,7 +23,6 @@ using BH.oM.Data.Collections; using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; namespace BH.Engine.Data { diff --git a/Serialiser_Engine/Objects/BsonSerializers/ObjectSerializer.cs b/Serialiser_Engine/Objects/BsonSerializers/ObjectSerializer.cs index a6b477cc8..4923ce3e1 100644 --- a/Serialiser_Engine/Objects/BsonSerializers/ObjectSerializer.cs +++ b/Serialiser_Engine/Objects/BsonSerializers/ObjectSerializer.cs @@ -193,8 +193,6 @@ private void SerializeDiscriminatedValue(BsonSerializationContext context, BsonS actualType = typeof(Type); else if (value is Enum) actualType = typeof(Enum); - else if (value is Delegate) - actualType = typeof(Delegate); var serializer = BsonSerializer.LookupSerializer(actualType); From 9fbf0890be4115c2dee5e122e8dd7761211b0e3c Mon Sep 17 00:00:00 2001 From: Eduardo Pignatelli Date: Tue, 13 Aug 2019 15:10:38 +0100 Subject: [PATCH 18/28] fix nestedmethods aggregation --- Reflection_Engine/Query/NestedMethods.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Reflection_Engine/Query/NestedMethods.cs b/Reflection_Engine/Query/NestedMethods.cs index ca923fbde..0eb9d26d5 100644 --- a/Reflection_Engine/Query/NestedMethods.cs +++ b/Reflection_Engine/Query/NestedMethods.cs @@ -33,14 +33,14 @@ public static partial class Query /**** Public Methods ****/ /***************************************************/ - public static List GetAllMethods(this Type type) + public static List NestedMethods(this Type type) { List methods = type.GetMethods().ToList(); Type[] nestedTypes = type.GetNestedTypes(); while (nestedTypes.Length > 0) { - methods.Concat(nestedTypes.SelectMany(x => x.GetMethods())); + methods.AddRange(nestedTypes.SelectMany(x => x.GetMethods())); nestedTypes = nestedTypes.SelectMany(x => x.GetNestedTypes()).ToArray(); } From 099556cea85649aba137326cfbac05fec4673ae3 Mon Sep 17 00:00:00 2001 From: Eduardo Pignatelli Date: Tue, 13 Aug 2019 15:10:56 +0100 Subject: [PATCH 19/28] make extraction of external methods more robust --- Reflection_Engine/Query/MethodList.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Reflection_Engine/Query/MethodList.cs b/Reflection_Engine/Query/MethodList.cs index 317c58f4f..a1cc25cf7 100644 --- a/Reflection_Engine/Query/MethodList.cs +++ b/Reflection_Engine/Query/MethodList.cs @@ -101,13 +101,14 @@ private static void ExtractAllMethods() m_BHoMMethodList.AddRange(typeMethods.Where(x => x.IsLegal())); } - if (type.Name == "External") + if (type.Name == "Query") { - List methods = type.GetMethod("ExternalMethods")?.Invoke(null, null) as List; - if (methods != null && methods.Count > 0) + MethodInfo method = type.GetMethod("ExternalMethods"); + if (method != null) { - m_ExternamMethodList.AddRange(methods); - //m_BHoMMethodList.AddRange(methods); + List externalMethods = method.Invoke(null, null) as List; + m_ExternamMethodList.AddRange(externalMethods); + m_BHoMMethodList.AddRange(externalMethods); } } // Get everything From 0acb971d8cf2cbf49b6ee0e7109e905c79cd8711 Mon Sep 17 00:00:00 2001 From: Eduardo Pignatelli Date: Tue, 13 Aug 2019 15:44:31 +0100 Subject: [PATCH 20/28] external methods should not be in the bhom method list --- Reflection_Engine/Query/MethodList.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/Reflection_Engine/Query/MethodList.cs b/Reflection_Engine/Query/MethodList.cs index a1cc25cf7..836e96835 100644 --- a/Reflection_Engine/Query/MethodList.cs +++ b/Reflection_Engine/Query/MethodList.cs @@ -108,7 +108,6 @@ private static void ExtractAllMethods() { List externalMethods = method.Invoke(null, null) as List; m_ExternamMethodList.AddRange(externalMethods); - m_BHoMMethodList.AddRange(externalMethods); } } // Get everything From cef75d2eaafe3cf16e74e347ad914fd7d158adc4 Mon Sep 17 00:00:00 2001 From: Eduardo Pignatelli Date: Fri, 16 Aug 2019 10:39:34 +0100 Subject: [PATCH 21/28] Store methods and constructors in one field - switch to MethodBase --- Reflection_Engine/Query/MethodList.cs | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/Reflection_Engine/Query/MethodList.cs b/Reflection_Engine/Query/MethodList.cs index 836e96835..1c4d0652d 100644 --- a/Reflection_Engine/Query/MethodList.cs +++ b/Reflection_Engine/Query/MethodList.cs @@ -61,13 +61,14 @@ public static List AllMethodList() /***************************************************/ - public static List ExternalMethodList() + public static List ExternalMethodList() { - // If the dictionary exists already return it - if (m_ExternamMethodList == null || m_ExternamMethodList.Count <= 0) + // Checking for an empty list may be dangerous, we should give different meaning to null and empty lists + // What if m_ExternalMethodList is empty after calling ExtractAllMethods() ? + if (m_ExternalMethodList == null || m_ExternalMethodList.Count <= 0) ExtractAllMethods(); - return m_ExternamMethodList; + return m_ExternalMethodList; } @@ -103,12 +104,12 @@ private static void ExtractAllMethods() if (type.Name == "Query") { - MethodInfo method = type.GetMethod("ExternalMethods"); - if (method != null) - { - List externalMethods = method.Invoke(null, null) as List; - m_ExternamMethodList.AddRange(externalMethods); - } + MethodInfo getExternalMethods = type.GetMethod("ExternalMethods"); + if (getExternalMethods != null) + m_ExternalMethodList.AddRange((List)getExternalMethods.Invoke(null, null)); + MethodInfo getExternalCtor = type.GetMethod("ExternalConstructors"); + if (getExternalCtor != null) + m_ExternalMethodList.AddRange((List)getExternalCtor.Invoke(null, null)); } // Get everything StoreAllMethods(type); @@ -148,7 +149,7 @@ private static void StoreAllMethods(Type type) private static List m_BHoMMethodList = new List(); private static List m_AllMethodList = new List(); - private static List m_ExternamMethodList = new List(); + private static List m_ExternalMethodList = new List(); /***************************************************/ } From b84f01db794483621dbfd1eb02a62aa8b9820d60 Mon Sep 17 00:00:00 2001 From: Eduardo Pignatelli Date: Fri, 16 Aug 2019 13:09:24 +0100 Subject: [PATCH 22/28] Settle on class and method names --- Reflection_Engine/Query/MethodList.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Reflection_Engine/Query/MethodList.cs b/Reflection_Engine/Query/MethodList.cs index 1c4d0652d..153c36ca2 100644 --- a/Reflection_Engine/Query/MethodList.cs +++ b/Reflection_Engine/Query/MethodList.cs @@ -102,12 +102,13 @@ private static void ExtractAllMethods() m_BHoMMethodList.AddRange(typeMethods.Where(x => x.IsLegal())); } - if (type.Name == "Query") + if (type.Name == "External") { - MethodInfo getExternalMethods = type.GetMethod("ExternalMethods"); + m_ExternalMethodList.AddRange(type.GetMethods()); + MethodInfo getExternalMethods = type.GetMethod("Methods"); if (getExternalMethods != null) m_ExternalMethodList.AddRange((List)getExternalMethods.Invoke(null, null)); - MethodInfo getExternalCtor = type.GetMethod("ExternalConstructors"); + MethodInfo getExternalCtor = type.GetMethod("Constructors"); if (getExternalCtor != null) m_ExternalMethodList.AddRange((List)getExternalCtor.Invoke(null, null)); } From 4c1ef993e1a4a5db7031cd6966323ed91a744572 Mon Sep 17 00:00:00 2001 From: Eduardo Pignatelli Date: Wed, 21 Aug 2019 12:17:15 +0100 Subject: [PATCH 23/28] rename MakeGeneric to MakeFromGeneric to be clearer --- Reflection_Engine/Create/MethodInfo.cs | 2 +- Reflection_Engine/Modify/MakeGeneric.cs | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Reflection_Engine/Create/MethodInfo.cs b/Reflection_Engine/Create/MethodInfo.cs index c99c23476..c53e5b7e4 100644 --- a/Reflection_Engine/Create/MethodInfo.cs +++ b/Reflection_Engine/Create/MethodInfo.cs @@ -51,7 +51,7 @@ public static MethodInfo MethodInfo(this Type declaringType, string methodName, { if (method.ContainsGenericParameters) { - Type[] generics = method.GetGenericArguments().Select(x => x.MakeGeneric()).ToArray(); + Type[] generics = method.GetGenericArguments().Select(x => x.MakeFromGeneric()).ToArray(); method = method.MakeGenericMethod(generics); parameters = method.GetParameters(); } diff --git a/Reflection_Engine/Modify/MakeGeneric.cs b/Reflection_Engine/Modify/MakeGeneric.cs index 57b4574a6..1d6b256cc 100644 --- a/Reflection_Engine/Modify/MakeGeneric.cs +++ b/Reflection_Engine/Modify/MakeGeneric.cs @@ -34,10 +34,10 @@ public static partial class Modify /**** Public Methods ****/ /***************************************************/ - [Description("Returns the specific type from a type that contains generic parameters")] + [Description("Returns the constraint type from a generic type")] [Input("genericType", "The generic type. Type is generic if Type.IsGenericParameter or Type.ContrainsGenericparameters is true")] [Output("type", "The specific type constructed from the generic one")] - public static Type MakeGeneric(this Type genericType) + public static Type MakeFromGeneric(this Type genericType) { if (genericType.IsGenericParameter) { @@ -49,7 +49,7 @@ public static Type MakeGeneric(this Type genericType) } else if (genericType.ContainsGenericParameters) { - Type[] constrains = genericType.GetGenericArguments().Select(x => MakeGeneric(x)).ToArray(); + Type[] constrains = genericType.GetGenericArguments().Select(x => MakeFromGeneric(x)).ToArray(); return genericType.GetGenericTypeDefinition().MakeGenericType(constrains); } else @@ -58,14 +58,14 @@ public static Type MakeGeneric(this Type genericType) /***************************************************/ - [Description("Returns the specific method from a method that contains generic parameters")] + [Description("Replaces the generic parameters with parameters whose type is their constraint, and returns a new MethodInfo from those")] [Input("genericMethod", "The generic method. Method is generic if MethodInfo.ContainsGenericParameter is true")] [Output("method", "The specific method constructed from the generic one")] - public static MethodInfo MakeGeneric(this MethodInfo genericMethod) + public static MethodInfo MakeFromGeneric(this MethodInfo genericMethod) { if (genericMethod.ContainsGenericParameters) { - Type[] types = genericMethod.GetGenericArguments().Select(x => x.MakeGeneric()).ToArray(); + Type[] types = genericMethod.GetGenericArguments().Select(x => x.MakeFromGeneric()).ToArray(); genericMethod = genericMethod.MakeGenericMethod(types); } From 266b17ce6bbe4dec30e1ecb02f41af5286e81e53 Mon Sep 17 00:00:00 2001 From: Eduardo Pignatelli Date: Wed, 21 Aug 2019 14:58:10 +0100 Subject: [PATCH 24/28] fix MakeFromGeneric file name --- Reflection_Engine/Modify/{MakeGeneric.cs => MakeFromGeneric.cs} | 0 Reflection_Engine/Reflection_Engine.csproj | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename Reflection_Engine/Modify/{MakeGeneric.cs => MakeFromGeneric.cs} (100%) diff --git a/Reflection_Engine/Modify/MakeGeneric.cs b/Reflection_Engine/Modify/MakeFromGeneric.cs similarity index 100% rename from Reflection_Engine/Modify/MakeGeneric.cs rename to Reflection_Engine/Modify/MakeFromGeneric.cs diff --git a/Reflection_Engine/Reflection_Engine.csproj b/Reflection_Engine/Reflection_Engine.csproj index c544053fa..44effaa7a 100644 --- a/Reflection_Engine/Reflection_Engine.csproj +++ b/Reflection_Engine/Reflection_Engine.csproj @@ -99,7 +99,7 @@ - + From a84af06c4136d704e8b3850122240e340730ffa7 Mon Sep 17 00:00:00 2001 From: Eduardo Pignatelli Date: Tue, 27 Aug 2019 09:13:21 +0100 Subject: [PATCH 25/28] removing the Reflection.Modify.MakeStatic method --- Reflection_Engine/Modify/MakeStatic.cs | 70 -------------------------- 1 file changed, 70 deletions(-) delete mode 100644 Reflection_Engine/Modify/MakeStatic.cs diff --git a/Reflection_Engine/Modify/MakeStatic.cs b/Reflection_Engine/Modify/MakeStatic.cs deleted file mode 100644 index ff82c3869..000000000 --- a/Reflection_Engine/Modify/MakeStatic.cs +++ /dev/null @@ -1,70 +0,0 @@ -/* - * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2019, the respective contributors. All rights reserved. - * - * Each contributor holds copyright over their respective contributions. - * The project versioning (Git) records all such contribution source information. - * - * - * The BHoM is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3.0 of the License, or - * (at your option) any later version. - * - * The BHoM is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this code. If not, see . - */ - -using BH.oM.Reflection.Attributes; -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -using System.Linq.Expressions; -using System.Reflection; - -namespace BH.Engine.Reflection -{ - public static partial class Modify - { - /***************************************************/ - /**** Public Methods ****/ - /***************************************************/ - - [Description("Returns the specific type from a type that contains generic parameters")] - [Input("method", "The generic type")] - [Output("type", "The specific type constructed from the generic one")] - public static MethodInfo MakeStatic(this MethodInfo method) - { - // This is not really true, the method will not be static after processing. - // This has to be fixed - - if (method == null) - return null; - - ParameterInfo[] parameters = method.GetParameters(); - - List parameterTypes = parameters.Select(x => x.ParameterType).ToList(); - parameterTypes.Add(method.ReturnType); - if (!method.IsStatic) - parameterTypes.Insert(0, method.DeclaringType); - - object firstArgument = method.IsStatic ? null : method.DeclaringType; - - if (method.IsGenericMethod || method.ContainsGenericParameters) - return null; //method = method.MakeGeneric(); - - Type delegateType = Expression.GetDelegateType(parameterTypes.ToArray()); - Delegate @delegate = Delegate.CreateDelegate(delegateType, method); - - return @delegate.Method; - } - - /***************************************************/ - } -} \ No newline at end of file From 6671d60ebbd2bc2f8d0a3fed2135ed5301d50742 Mon Sep 17 00:00:00 2001 From: Eduardo Pignatelli Date: Tue, 27 Aug 2019 09:31:38 +0100 Subject: [PATCH 26/28] pushing the csproj file --- Reflection_Engine/Reflection_Engine.csproj | 1 - 1 file changed, 1 deletion(-) diff --git a/Reflection_Engine/Reflection_Engine.csproj b/Reflection_Engine/Reflection_Engine.csproj index 44effaa7a..0db49ed76 100644 --- a/Reflection_Engine/Reflection_Engine.csproj +++ b/Reflection_Engine/Reflection_Engine.csproj @@ -100,7 +100,6 @@ - From 31c59fdc894705859baf55e9eb0f90758e636213 Mon Sep 17 00:00:00 2001 From: Eduardo Pignatelli Date: Tue, 27 Aug 2019 10:27:47 +0100 Subject: [PATCH 27/28] Remove gatherer methods from the list of external methods --- Reflection_Engine/Query/MethodList.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/Reflection_Engine/Query/MethodList.cs b/Reflection_Engine/Query/MethodList.cs index 153c36ca2..3b827023d 100644 --- a/Reflection_Engine/Query/MethodList.cs +++ b/Reflection_Engine/Query/MethodList.cs @@ -104,7 +104,6 @@ private static void ExtractAllMethods() if (type.Name == "External") { - m_ExternalMethodList.AddRange(type.GetMethods()); MethodInfo getExternalMethods = type.GetMethod("Methods"); if (getExternalMethods != null) m_ExternalMethodList.AddRange((List)getExternalMethods.Invoke(null, null)); From 54b498f03e68ef4c3a1e81ea38e949b9ec702a13 Mon Sep 17 00:00:00 2001 From: Eduardo Pignatelli Date: Tue, 27 Aug 2019 15:01:50 +0100 Subject: [PATCH 28/28] adding check for null namespace yes, it can happen, I don't know how --- Reflection_Engine/Convert/ToText.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Reflection_Engine/Convert/ToText.cs b/Reflection_Engine/Convert/ToText.cs index 507816031..ef6b58919 100644 --- a/Reflection_Engine/Convert/ToText.cs +++ b/Reflection_Engine/Convert/ToText.cs @@ -81,7 +81,7 @@ public static string ToText(this Type type, bool includePath = false, bool repla { Type[] types = type.GetGenericArguments(); - if (replaceGeneric && types.Count() == 1 && !type.Namespace.StartsWith("BH")) + if (replaceGeneric && types.Count() == 1 && type.Namespace != null && !type.Namespace.StartsWith("BH")) return types[0].ToText(includePath, replaceGeneric); else {