dotnet / dotnet/macios

[RFC] Provide a better API to convert NSObject to a protocol interface

Open
#3,887 6 comments 3 reactions 0 assignees View on GitHub
enhancement iOS macOS request-for-comments
Dominant language
C#
Stars
2.9k
Forks
576
Avg merge
2d 12h
Merged PRs (30d)
123

Description

[Exhibit A](https://github.com/crmann1/azure-activedirectory-library-for-dotnet/blob/5f04630810a17e32f9a6d3250dc1075749a61d0d/src/ADAL.PCL.iOS/AdalCustomUrlProtocol.cs#L92)

```csharp
INSUrlProtocolClient client;
public CustomNSUrlConnectionDataDelegate (CustomNSUrlProtocol handler)
{
client = (INSUrlProtocolClient)handler.WeakClient;
}
```

this pattern is broken, because `handler.WeakClient` is typed as an NSObject, and you may not get an instance of a NSUrlProtocol subclass back, in which case you end up with an InvalidCastException.

Unfortunately it's very easy to do this mistake in C#, and the correct code is not at all obvious:

```csharp
INSUrlProtocolClient client;
public CustomNSUrlConnectionDataDelegate (CustomNSUrlProtocol handler)
{
client = Runtime.GetINativeObject (handler.WeakClient.Handle, false);
}
```

so I suggest something else:

```csharp
class NSObject {
public T AsProtocol () where T: class, INativeObject
{
if (!typeof (T).IsInterface)
throw new ArgumentException ($"{typeof (T)}.FullName is not an interface");
// ...
// verify that T is an interface representing a protocol

var rv = this as T;
if (rv != null)
return rv;
return Runtime.GetINativeObject (Handle, false);
}
}

INSUrlProtocolClient client;
public CustomNSUrlConnectionDataDelegate (CustomNSUrlProtocol handler)
{
client = handler?.WeakClient.AsProtocol ();
}
```

this should be much more discoverable.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.