Skip to content

Commit

Permalink
[managed-static-registrar] Remove use of reflection in UCOs of generi…
Browse files Browse the repository at this point in the history
…c types (#18421)

Closes #18356

In the static UnmanagedCallersOnly methods we don't know the generic
parameters of the type we're working with and we need to use this trick
to be able to call methods on the generic type without using reflection.
When we call a non-generic interface method implemented on a generic
class, the .NET runtime will resolve the generic parameters for us. In
the implementation of the interface method, we can simply use the
generic parameters and generate the same code we usually generate in the
UnmanagedCallersOnly callback method.

This is an example of the code we generate in addition to user code:

```csharp
internal interface __IRegistrarGenericTypeProxy__CustomNSObject_1__
{
	void __IRegistrarGenericTypeProxy__CustomNSObject_1____SomeMethod (IntPtr p0);
}

public class CustomNSObject<T> : NSObject, __IRegistrarGenericTypeProxy__CustomNSObject_1__
	where T : NSObject
{
	[Export ("someMethod:")]
	public void SomeMethod (T someInput)
	{
		// ...
	}

	// generated implementation of the proxy interface:
	public void __IRegistrarGenericTypeProxy__CustomNSObject_1____SomeMethod (IntPtr sel, IntPtr p0, IntPtr* exception_gchandle)
	{
		try {
			var obj0 = (T) Runtime.GetNSObject<T> (p0);
			SomeMethod (obj0);
		} catch (Exception ex) {
			*exception_gchandle = Runtime.AllocGCHandle (ex);
		}
	}

	// generated registrar callbacks:
	private static class __Registrar_Callbacks__
	{
		[UnmanagedCallersOnly (EntryPoint = "_callback_1_CustomNSObject_1_SomeMethod")]
		public unsafe static void callback_1_CustomNSObject_1_SomeMethod (IntPtr pobj, IntPtr sel, IntPtr p0, IntPtr* exception_gchandle)
		{
			var proxy = (__IRegistrarGenericTypeProxy__CustomNSObject_1__)Runtime.GetNSObject (pobj);
			proxy.__IRegistrarGenericTypeProxy__CustomNSObject_1____SomeMethod (sel, p0, exception_gchandle);
		}
	}
}
```
```csharp
// regular non-generic class for comparison:
public class CustomNSObject : NSObject
	where T : NSObject
{
	[Export ("someMethod:")]
	public void SomeMethod (NSSet someInput)
	{
		// ...
	}
	
	private static class __Registrar_Callbacks__
	{
		[UnmanagedCallersOnly (EntryPoint = "_callback_1_CustomNSObject_1_SomeMethod")]
		public unsafe static void callback_1_CustomNSObject_1_SomeMethod (IntPtr pobj, IntPtr sel, IntPtr p0, IntPtr* exception_gchandle)
		{
			try {
				NSSet obj0 = Runtime.GetNSObject<NSSet> (p0);
				SomeMethod (obj0);
			} catch (Exception ex) {
				*exception_gchandle = Runtime.AllocGCHandle (ex);
			}
		}
	}
}
```

---------

Co-authored-by: Alex Soto <[email protected]>
  • Loading branch information
simonrozsival and dalexsoto authored Jun 28, 2023
1 parent 3f6d43c commit 6010c13
Showing 1 changed file with 161 additions and 127 deletions.
Loading

6 comments on commit 6010c13

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

Please sign in to comment.