-
Notifications
You must be signed in to change notification settings - Fork 15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Prototyping reflection of external libraries #1132
Prototyping reflection of external libraries #1132
Conversation
…nder one delegate type `Func<object[], object>`
return method; | ||
|
||
// So, let's try the other overload | ||
return MethodBase(type, methodName, paramTypes.Select(x => x.Name).ToList()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Uses the old overload in case the new fails when dealing with generic types (I believe around 10% of the cases, maybe less)
/**** Public Methods ****/ | ||
/*************************************/ | ||
|
||
public static MethodInfo MethodInfo(this Type declaringType, string methodName, List<Type> paramTypes) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Migration from the BHoM_UI
[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) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method is not correct, because I was not really able to convert an instance method into a static method.. Thus, it is not really used. We may consider removing it altogether.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I suppose you now have figured out why it cannot work after your work on the UI side.
I would suggest to remove this then. No point on leaving public methods that don't work in the code.
/**** Public Methods - Interfaces ****/ | ||
/***************************************************/ | ||
|
||
public static bool IIsExposed(this object obj) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one centralises the check of what to reflect to the UIs.
The current approach spreads around a combination of IsNotImplemented
and IsDeprecated
.
@@ -59,6 +59,18 @@ public static List<MethodBase> AllMethodList() | |||
return m_AllMethodList; | |||
} | |||
|
|||
/***************************************************/ | |||
|
|||
public static List<MethodBase> ExternalMethodList() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one collects the methods that come from external libraries.
I have chosen to store the methods into a standalone field to avoid contaminating the other ones.
The reason is that the namespace of the methods the field stores do not start with BH
.
/**** Public Methods ****/ | ||
/***************************************************/ | ||
|
||
public static List<MethodInfo> NestedMethods(this Type type) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This add the feature to retrieve methods declared in nested classes
@@ -88,18 +88,20 @@ public override MethodBase Deserialize(BsonDeserializationContext context, BsonD | |||
bsonReader.ReadName(); | |||
string methodName = bsonReader.ReadString(); | |||
|
|||
List<string> paramTypes = new List<string>(); | |||
List<string> paramTypesJson = new List<string>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this improves the clarity of the variable: it's not the name of the type, it is its json representation
bsonReader.ReadEndArray(); | ||
|
||
context.Reader.ReadEndDocument(); | ||
|
||
try | ||
{ | ||
MethodBase method = Create.MethodBase((Type)Convert.FromJson(typeName), methodName, paramTypes); | ||
List<Type> types = paramTypesJson.Select(x => Convert.FromJson(x)).Cast<Type>().ToList(); | ||
MethodBase method = Create.MethodBase((Type)Convert.FromJson(typeName), methodName, types); // type overload |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Passing the actual types to the reflection engine. In the current master, Create.MethodBase
lies in the Serialisation_Engine exactly because paramTypes
is a json string, and not the name of the method.
By deserialising the types before the method call allows us to move the Create.MethodBase
in its correct namespase: Engine.Reflection
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left some comments in the code to help reviewing this pr
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Globally happy with the changes. Well done :-)
Just one thing to change :-)
[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) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I suppose you now have figured out why it cannot work after your work on the UI side.
I would suggest to remove this then. No point on leaving public methods that don't work in the code.
Thanks @adecler - yeah, that method doesn't have reason to exist. |
yes, it can happen, I don't know how
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All look good to me. 👍
There is no actual code-wise dependency.
Although, to test the prototype, you need to switch to the correspondent (identically named) branches in the BHoM_UI and the Grasshopper_Toolkit, and this pr from the Numpy_Toolkit: BHoM/Numpy_Toolkit#2
Issues addressed by this PR
Closes #1131
This pr is adding a way to reflect assemblies that are not BHoM-compliant, but can be useful in the BHoM workflow.
I have put together a quick wiki for a more exhaustive explanation of the principles I followed, and how to implement another in the future: https://github.com/BHoM/documentation/wiki/The-%60External%60-class
The other main change is this pr is the migration of some of the methods from the UI, that was not really in the best place.
I will put specific comments on the diffs to explain them, I think it is easier to explain and review without missing something.
Test files
The test comes with the PR on the Numpy_Toolkit: BHoM/Numpy_Toolkit#2
Changelog
GroupMethodsByName
from the UI to theData_Engine
and renamed it toGroupByName
, since it is a generic methodCompileFunction
toEngine.Reflection.Convert.ToFunc
in order to transform any delegate to aFunc<object[], object>
void
Engine.Serialiser.Create.MethodBase
toEngine.Reflection.Create.MethodBase
. TheList<string> paramTypes
now is the list of name of the types, rather than their json representationMethodBase
s via aList<Type>
as well, for robustness and performanceEngine.Serialiser.Create.MethodInfo
toEngine.Reflection.Create.MethodInfo
IsExposed
method to centralise the check of which methods to expose to the UIs.Engine.Reflection.Query.ExternalMethodList
as a way to collect methods from external libraries