Skip to content
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

Issue 1649 #1651

Merged
merged 6 commits into from
Mar 23, 2025
Merged

Issue 1649 #1651

merged 6 commits into from
Mar 23, 2025

Conversation

CharliePoole
Copy link
Member

This may fix #1649, depending on the discussion on the issue itself.

Copy link
Member

@manfred-brands manfred-brands left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few issues in the ExtensionWrapper. Main one that the cache wasn't working.
I added a commit to fix these.

For the rest look good.


namespace NUnit.Extensibility
{
using Wrappers;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like using statements in 2 places in the same file.
As it isn't used anywhere else in the project, I would prefer to move this outside the namespace declaration.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved by me.

Comment on lines 15 to 16
private object _wrappedInstance;
private Type _wrappedType;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The can be declared readonly

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

private struct MethodSignature
{
public string Name;
public object[] ArgTypes;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this not be Type[]?
I know this type only exists for the sake of the Dictionary.
However it doesn't work.
Even though this type is declared a struct, the structural equality doesn't work on class members such as the array. It fails as soon as the arrays are not the same instance which is every time as the array is re-created for every call.

I added a test to verify the cache is working.

Comment on lines 4 to 8
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A lot of unnecessary using statements.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed.


protected void Invoke(string methodName, params object[] args)
{
WrapMethod(methodName, Type.GetTypeArray(args)).Invoke(_wrappedInstance, args);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although elegant, there are two problem with Type.GetTypeArray.
It doesn't support null arguments as you can't get the type of null.
I don't see any of your wrappers allowing null. So it might not be relevant.
The other problem is that you get a new array every call which means that the MethodSignature key is different and there is no caching. To a lesser extent it is a small hit on the GC, but with this calling reflection that would be irrelevant.
I can fix the caching by overriding GetHashCode and Equals, but as the signature is fixed at compile time, it would be better to pass the types in.

I added overloads allowing passing in the ArgTypes.
I also added overloads for the common method that have one string argument.

protected T Invoke<T>(string methodName, params object[] args)
{
Console.WriteLine($"Wrapper called for {typeof(T)} {methodName}");
if (args == null) args = Array.Empty<object>();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would only happen if the derived class explicitly passes in null. Not if they pass in no parameters.

@@ -88,18 +87,42 @@ private PropertyInfo WrapProperty(string propertyName)
return prop;
}

private struct MethodSignature
internal IEnumerable<MethodSignature> GetMethodSignatures() => _methods.Keys;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding a method to permit testing is a good idea!

@CharliePoole CharliePoole merged commit 8d2c7cc into version4 Mar 23, 2025
4 checks passed
@CharliePoole CharliePoole deleted the issue-1649 branch March 23, 2025 07:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants