[CF[Read|Write|HTTP]Stream] Subclass NativeObject + numerous other code updates (#13127)

* Subclass NativeObject to reuse object lifetime code.
* Enable nullability and fix code accordingly.
* Use 'is' and 'is not' instead of '==' and '!=' for object identity.
* Use the null-safe NativeObjectExtensions.GetHandle extension method to get
  the handle instead of checking for null (avoids some code duplication).
* Use 'nameof (parameter)' instead of string constants.
* Call 'GetCheckedHandle ()' (which will throw an ObjectDisposedException if
  Handle == IntPtr.Zero) instead of manually checking for IntPtr.Zero and
  throwing ObjectDisposedException.
* Use Array.Empty<T> instead of creating an empty array manually.
* Remove the (IntPtr) constructor for XAMCORE_4_0.
* Add an internal (IntPtr, bool) constructor.
This commit is contained in:
Rolf Bjarne Kvinge 2021-10-27 10:20:57 +02:00 коммит произвёл GitHub
Родитель cf8008cbc0
Коммит a28fc44056
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
4 изменённых файлов: 146 добавлений и 153 удалений

Просмотреть файл

@ -7,6 +7,8 @@
// Copyright 2012-2015 Xamarin Inc. (http://www.xamarin.com) // Copyright 2012-2015 Xamarin Inc. (http://www.xamarin.com)
// //
#nullable enable
using System; using System;
using Foundation; using Foundation;
using CoreFoundation; using CoreFoundation;
@ -28,12 +30,12 @@ namespace CoreServices {
#endif #endif
public partial class CFHTTPStream : CFReadStream { public partial class CFHTTPStream : CFReadStream {
internal CFHTTPStream (IntPtr handle) internal CFHTTPStream (IntPtr handle, bool owns)
: base (handle) : base (handle, owns)
{ {
} }
public Uri FinalURL { public Uri? FinalURL {
get { get {
var handle = GetProperty (_FinalURL); var handle = GetProperty (_FinalURL);
if (handle == IntPtr.Zero) if (handle == IntPtr.Zero)
@ -44,12 +46,12 @@ namespace CoreServices {
throw new InvalidCastException (); throw new InvalidCastException ();
} }
using (var url = new CFUrl (handle)) using (var url = new CFUrl (handle, false))
return new Uri (url.ToString ()); return new Uri (url.ToString ());
} }
} }
public CFHTTPMessage GetFinalRequest () public CFHTTPMessage? GetFinalRequest ()
{ {
var handle = GetProperty (_FinalRequest); var handle = GetProperty (_FinalRequest);
if (handle == IntPtr.Zero) if (handle == IntPtr.Zero)
@ -63,7 +65,7 @@ namespace CoreServices {
return new CFHTTPMessage (handle, true); return new CFHTTPMessage (handle, true);
} }
public CFHTTPMessage GetResponseHeader () public CFHTTPMessage? GetResponseHeader ()
{ {
var handle = GetProperty (_ResponseHeader); var handle = GetProperty (_ResponseHeader);
if (handle == IntPtr.Zero) if (handle == IntPtr.Zero)
@ -132,8 +134,8 @@ namespace CoreServices {
#if !WATCHOS #if !WATCHOS
public void SetProxy (CFProxySettings proxySettings) public void SetProxy (CFProxySettings proxySettings)
{ {
if (proxySettings == null) if (proxySettings is null)
throw new ArgumentNullException ("proxySettings"); throw new ArgumentNullException (nameof (proxySettings));
SetProperty (_Proxy, proxySettings.Dictionary); SetProperty (_Proxy, proxySettings.Dictionary);
} }

Просмотреть файл

@ -27,11 +27,9 @@
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// //
#nullable enable
using System; using System;
using System.IO;
using System.Text;
using System.Reflection;
using System.Threading;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using CoreFoundation; using CoreFoundation;
using Foundation; using Foundation;
@ -43,15 +41,22 @@ namespace CoreFoundation {
// CFStream.h // CFStream.h
public class CFReadStream : CFStream { public class CFReadStream : CFStream {
#if !XAMCORE_4_0
public CFReadStream (IntPtr handle) public CFReadStream (IntPtr handle)
: base (handle) : base (handle, true)
{
}
#endif
internal CFReadStream (IntPtr handle, bool owns)
: base (handle, owns)
{ {
} }
[DllImport (Constants.CoreFoundationLibrary)] [DllImport (Constants.CoreFoundationLibrary)]
extern static /* CFErrorRef */ IntPtr CFReadStreamCopyError (/* CFReadStreamRef */ IntPtr stream); extern static /* CFErrorRef */ IntPtr CFReadStreamCopyError (/* CFReadStreamRef */ IntPtr stream);
public override CFException GetError () public override CFException? GetError ()
{ {
var error = CFReadStreamCopyError (Handle); var error = CFReadStreamCopyError (Handle);
if (error == IntPtr.Zero) if (error == IntPtr.Zero)
@ -96,36 +101,36 @@ namespace CoreFoundation {
[DllImport (Constants.CoreFoundationLibrary)] [DllImport (Constants.CoreFoundationLibrary)]
extern static void CFReadStreamScheduleWithRunLoop (/* CFReadStreamRef */ IntPtr stream, /* CFRunLoopRef */ IntPtr runLoop, /* CFStringRef */ IntPtr runLoopMode); extern static void CFReadStreamScheduleWithRunLoop (/* CFReadStreamRef */ IntPtr stream, /* CFRunLoopRef */ IntPtr runLoop, /* CFStringRef */ IntPtr runLoopMode);
protected override void ScheduleWithRunLoop (CFRunLoop loop, NSString mode) protected override void ScheduleWithRunLoop (CFRunLoop loop, NSString? mode)
{ {
if (loop == null) if (loop is null)
throw new ArgumentNullException ("loop"); throw new ArgumentNullException (nameof (loop));
if (mode == null) if (mode is null)
throw new ArgumentNullException ("mode"); throw new ArgumentNullException (nameof (mode));
CFReadStreamScheduleWithRunLoop (Handle, loop.Handle, mode.Handle); CFReadStreamScheduleWithRunLoop (Handle, loop.Handle, mode.Handle);
} }
[DllImport (Constants.CoreFoundationLibrary)] [DllImport (Constants.CoreFoundationLibrary)]
extern static void CFReadStreamUnscheduleFromRunLoop (/* CFReadStreamRef */ IntPtr stream, /* CFRunLoopRef */ IntPtr runLoop, /* CFStringRef */ IntPtr runLoopMode); extern static void CFReadStreamUnscheduleFromRunLoop (/* CFReadStreamRef */ IntPtr stream, /* CFRunLoopRef */ IntPtr runLoop, /* CFStringRef */ IntPtr runLoopMode);
protected override void UnscheduleFromRunLoop (CFRunLoop loop, NSString mode) protected override void UnscheduleFromRunLoop (CFRunLoop loop, NSString? mode)
{ {
if (loop == null) if (loop is null)
throw new ArgumentNullException ("loop"); throw new ArgumentNullException (nameof (loop));
if (mode == null) if (mode is null)
throw new ArgumentNullException ("mode"); throw new ArgumentNullException (nameof (mode));
CFReadStreamUnscheduleFromRunLoop (Handle, loop.Handle, mode.Handle); CFReadStreamUnscheduleFromRunLoop (Handle, loop.Handle, mode.Handle);
} }
[DllImport (Constants.CoreFoundationLibrary)] [DllImport (Constants.CoreFoundationLibrary)]
[return: MarshalAs (UnmanagedType.I1)] [return: MarshalAs (UnmanagedType.I1)]
static extern bool CFReadStreamSetClient (/* CFReadStreamRef */ IntPtr stream, /* CFOptionFlags */ nint streamEvents, static extern bool CFReadStreamSetClient (/* CFReadStreamRef */ IntPtr stream, /* CFOptionFlags */ nint streamEvents,
/* CFReadStreamClientCallBack */ CFStreamCallback clientCB, /* CFStreamClientContext* */ IntPtr clientContext); /* CFReadStreamClientCallBack */ CFStreamCallback? clientCB, /* CFStreamClientContext* */ IntPtr clientContext);
protected override bool DoSetClient (CFStreamCallback callback, CFIndex eventTypes, protected override bool DoSetClient (CFStreamCallback? callback, CFIndex eventTypes,
IntPtr context) IntPtr context)
{ {
return CFReadStreamSetClient (Handle, eventTypes, callback, context); return CFReadStreamSetClient (Handle, (nint) eventTypes, callback, context);
} }
[DllImport (Constants.CoreFoundationLibrary)] [DllImport (Constants.CoreFoundationLibrary)]
@ -133,16 +138,16 @@ namespace CoreFoundation {
public nint Read (byte[] buffer) public nint Read (byte[] buffer)
{ {
if (buffer == null) if (buffer is null)
throw new ArgumentNullException ("buffer"); throw new ArgumentNullException (nameof (buffer));
return Read (buffer, 0, buffer.Length); return Read (buffer, 0, buffer.Length);
} }
public unsafe nint Read (byte[] buffer, int offset, int count) public unsafe nint Read (byte[] buffer, int offset, int count)
{ {
if (buffer == null) if (buffer is null)
throw new ArgumentNullException ("buffer"); throw new ArgumentNullException (nameof (buffer));
CheckHandle (); GetCheckedHandle ();
if (offset < 0) if (offset < 0)
throw new ArgumentException (); throw new ArgumentException ();
if (count < 1) if (count < 1)
@ -158,8 +163,8 @@ namespace CoreFoundation {
protected override IntPtr DoGetProperty (NSString name) protected override IntPtr DoGetProperty (NSString name)
{ {
if (name == null) if (name is null)
throw new ArgumentNullException ("name"); throw new ArgumentNullException (nameof (name));
return CFReadStreamCopyProperty (Handle, name.Handle); return CFReadStreamCopyProperty (Handle, name.Handle);
} }
@ -167,11 +172,11 @@ namespace CoreFoundation {
[return: MarshalAs (UnmanagedType.I1)] [return: MarshalAs (UnmanagedType.I1)]
extern static /* Boolean */ bool CFReadStreamSetProperty (/* CFReadStreamRef */ IntPtr stream, /* CFStreamRef */ IntPtr propertyName, /* CFTypeRef */ IntPtr propertyValue); extern static /* Boolean */ bool CFReadStreamSetProperty (/* CFReadStreamRef */ IntPtr stream, /* CFStreamRef */ IntPtr propertyName, /* CFTypeRef */ IntPtr propertyValue);
protected override bool DoSetProperty (NSString name, INativeObject value) protected override bool DoSetProperty (NSString name, INativeObject? value)
{ {
if (name == null) if (name is null)
throw new ArgumentNullException ("name"); throw new ArgumentNullException (nameof (name));
return CFReadStreamSetProperty (Handle, name.Handle, value == null ? IntPtr.Zero : value.Handle); return CFReadStreamSetProperty (Handle, name.Handle, value.GetHandle ());
} }
} }
} }

Просмотреть файл

@ -30,6 +30,8 @@
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// //
#nullable enable
using System; using System;
using System.Net; using System.Net;
using System.Net.Sockets; using System.Net.Sockets;
@ -84,14 +86,13 @@ namespace CoreFoundation {
CFReadStreamRef_InvokeRelease (release, Info); CFReadStreamRef_InvokeRelease (release, Info);
} }
public override string ToString () public override string? ToString ()
{ {
if (copyDescription != IntPtr.Zero) { if (copyDescription != IntPtr.Zero) {
var ptr = CFReadStreamRef_InvokeCopyDescription (copyDescription, Info); var ptr = CFReadStreamRef_InvokeCopyDescription (copyDescription, Info);
if (ptr != IntPtr.Zero) { if (ptr != IntPtr.Zero) {
// Copy* -> so we must not retain again // Copy* -> so we must not retain again
using (var s = new CFString (ptr, true)) return CFString.FromHandle (ptr, true);
return s.ToString ();
} }
} }
return base.ToString (); return base.ToString ();
@ -151,11 +152,10 @@ namespace CoreFoundation {
Error Error
} }
public abstract class CFStream : CFType, INativeObject, IDisposable { public abstract class CFStream : CFType {
IntPtr handle;
GCHandle gch; GCHandle gch;
CFRunLoop loop; CFRunLoop? loop;
NSString loopMode; NSString? loopMode;
bool open, closed; bool open, closed;
#region Stream Constructors #region Stream Constructors
@ -209,13 +209,13 @@ namespace CoreFoundation {
public static void CreatePairWithSocket (CFSocket socket, out CFReadStream readStream, public static void CreatePairWithSocket (CFSocket socket, out CFReadStream readStream,
out CFWriteStream writeStream) out CFWriteStream writeStream)
{ {
if (socket == null) if (socket is null)
throw new ArgumentNullException ("socket"); throw new ArgumentNullException (nameof (socket));
IntPtr read, write; IntPtr read, write;
CFStreamCreatePairWithSocket (IntPtr.Zero, socket.GetNative (), out read, out write); CFStreamCreatePairWithSocket (IntPtr.Zero, socket.GetNative (), out read, out write);
readStream = new CFReadStream (read); readStream = new CFReadStream (read, true);
writeStream = new CFWriteStream (write); writeStream = new CFWriteStream (write, true);
} }
#if !NET #if !NET
@ -274,8 +274,8 @@ namespace CoreFoundation {
var sig = new CFSocketSignature (family, type, proto, address); var sig = new CFSocketSignature (family, type, proto, address);
IntPtr read, write; IntPtr read, write;
CFStreamCreatePairWithPeerSocketSignature (IntPtr.Zero, ref sig, out read, out write); CFStreamCreatePairWithPeerSocketSignature (IntPtr.Zero, ref sig, out read, out write);
readStream = new CFReadStream (read); readStream = new CFReadStream (read, true);
writeStream = new CFWriteStream (write); writeStream = new CFWriteStream (write, true);
} }
} }
@ -331,15 +331,15 @@ namespace CoreFoundation {
#endif #endif
#endif #endif
public static void CreatePairWithSocketToHost (IPEndPoint endpoint, public static void CreatePairWithSocketToHost (IPEndPoint endpoint,
out CFReadStream readStream, out CFReadStream? readStream,
out CFWriteStream writeStream) out CFWriteStream? writeStream)
{ {
using (var host = CFHost.Create (endpoint)) { using (var host = CFHost.Create (endpoint)) {
IntPtr read, write; IntPtr read, write;
CFStreamCreatePairWithSocketToCFHost (IntPtr.Zero, host.Handle, endpoint.Port, out read, out write); CFStreamCreatePairWithSocketToCFHost (IntPtr.Zero, host.Handle, endpoint.Port, out read, out write);
// API can return null streams // API can return null streams
readStream = read == IntPtr.Zero ? null : new CFReadStream (read); readStream = read == IntPtr.Zero ? null : new CFReadStream (read, true);
writeStream = write == IntPtr.Zero ? null : new CFWriteStream (write); writeStream = write == IntPtr.Zero ? null : new CFWriteStream (write, true);
} }
} }
#endif #endif
@ -392,16 +392,16 @@ namespace CoreFoundation {
#endif #endif
#endif #endif
public static void CreatePairWithSocketToHost (string host, int port, public static void CreatePairWithSocketToHost (string host, int port,
out CFReadStream readStream, out CFReadStream? readStream,
out CFWriteStream writeStream) out CFWriteStream? writeStream)
{ {
using (var str = new CFString (host)) { using (var str = new CFString (host)) {
IntPtr read, write; IntPtr read, write;
CFStreamCreatePairWithSocketToHost ( CFStreamCreatePairWithSocketToHost (
IntPtr.Zero, str.Handle, port, out read, out write); IntPtr.Zero, str.Handle, port, out read, out write);
// API not annotated (yet?) but it's safe to bet it match CFStreamCreatePairWithSocketToCFHost // API not annotated (yet?) but it's safe to bet it match CFStreamCreatePairWithSocketToCFHost
readStream = read == IntPtr.Zero ? null : new CFReadStream (read); readStream = read == IntPtr.Zero ? null : new CFReadStream (read, true);
writeStream = write == IntPtr.Zero ? null : new CFWriteStream (write); writeStream = write == IntPtr.Zero ? null : new CFWriteStream (write, true);
} }
} }
#if !WATCH #if !WATCH
@ -431,11 +431,11 @@ namespace CoreFoundation {
#endif #endif
public static CFHTTPStream CreateForHTTPRequest (CFHTTPMessage request) public static CFHTTPStream CreateForHTTPRequest (CFHTTPMessage request)
{ {
if (request == null) if (request is null)
throw new ArgumentNullException ("request"); throw new ArgumentNullException (nameof (request));
var handle = CFReadStreamCreateForHTTPRequest (IntPtr.Zero, request.Handle); var handle = CFReadStreamCreateForHTTPRequest (IntPtr.Zero, request.Handle);
return new CFHTTPStream (handle); return new CFHTTPStream (handle, true);
} }
// CFHTTPStream.h in CFNetwork.framework (not CoreFoundation) // CFHTTPStream.h in CFNetwork.framework (not CoreFoundation)
@ -465,24 +465,24 @@ namespace CoreFoundation {
#endif #endif
public static CFHTTPStream CreateForStreamedHTTPRequest (CFHTTPMessage request, CFReadStream body) public static CFHTTPStream CreateForStreamedHTTPRequest (CFHTTPMessage request, CFReadStream body)
{ {
if (request == null) if (request is null)
throw new ArgumentNullException ("request"); throw new ArgumentNullException (nameof (request));
if (body == null) if (body is null)
throw new ArgumentNullException ("body"); throw new ArgumentNullException (nameof (body));
var handle = CFReadStreamCreateForStreamedHTTPRequest (IntPtr.Zero, request.Handle, body.Handle); var handle = CFReadStreamCreateForStreamedHTTPRequest (IntPtr.Zero, request.Handle, body.Handle);
return new CFHTTPStream (handle); return new CFHTTPStream (handle, true);
} }
public static CFHTTPStream CreateForStreamedHTTPRequest (CFHTTPMessage request, NSInputStream body) public static CFHTTPStream CreateForStreamedHTTPRequest (CFHTTPMessage request, NSInputStream body)
{ {
if (request == null) if (request is null)
throw new ArgumentNullException ("request"); throw new ArgumentNullException (nameof (request));
if (body == null) if (body is null)
throw new ArgumentNullException ("body"); throw new ArgumentNullException (nameof (body));
var handle = CFReadStreamCreateForStreamedHTTPRequest (IntPtr.Zero, request.Handle, body.Handle); var handle = CFReadStreamCreateForStreamedHTTPRequest (IntPtr.Zero, request.Handle, body.Handle);
return new CFHTTPStream (handle); return new CFHTTPStream (handle, true);
} }
#endif #endif
@ -495,15 +495,15 @@ namespace CoreFoundation {
{ {
IntPtr read, write; IntPtr read, write;
CFStreamCreateBoundPair (IntPtr.Zero, out read, out write, bufferSize); CFStreamCreateBoundPair (IntPtr.Zero, out read, out write, bufferSize);
readStream = new CFReadStream (read); readStream = new CFReadStream (read, true);
writeStream = new CFWriteStream (write); writeStream = new CFWriteStream (write, true);
} }
#endregion #endregion
#region Stream API #region Stream API
public abstract CFException GetError (); public abstract CFException? GetError ();
protected void CheckError () protected void CheckError ()
{ {
@ -516,7 +516,7 @@ namespace CoreFoundation {
{ {
if (open || closed) if (open || closed)
throw new InvalidOperationException (); throw new InvalidOperationException ();
CheckHandle (); GetCheckedHandle ();
if (!DoOpen ()) { if (!DoOpen ()) {
CheckError (); CheckError ();
throw new InvalidOperationException (); throw new InvalidOperationException ();
@ -530,8 +530,8 @@ namespace CoreFoundation {
{ {
if (!open) if (!open)
return; return;
CheckHandle (); GetCheckedHandle ();
if (loop != null) { if (loop is not null) {
DoSetClient (null, (CFIndex) 0, IntPtr.Zero); DoSetClient (null, (CFIndex) 0, IntPtr.Zero);
UnscheduleFromRunLoop (loop, loopMode); UnscheduleFromRunLoop (loop, loopMode);
loop = null; loop = null;
@ -549,7 +549,7 @@ namespace CoreFoundation {
public CFStreamStatus GetStatus () public CFStreamStatus GetStatus ()
{ {
CheckHandle (); GetCheckedHandle ();
return DoGetStatus (); return DoGetStatus ();
} }
@ -557,17 +557,17 @@ namespace CoreFoundation {
internal IntPtr GetProperty (NSString name) internal IntPtr GetProperty (NSString name)
{ {
CheckHandle (); GetCheckedHandle ();
return DoGetProperty (name); return DoGetProperty (name);
} }
protected abstract IntPtr DoGetProperty (NSString name); protected abstract IntPtr DoGetProperty (NSString name);
protected abstract bool DoSetProperty (NSString name, INativeObject value); protected abstract bool DoSetProperty (NSString name, INativeObject? value);
internal void SetProperty (NSString name, INativeObject value) internal void SetProperty (NSString name, INativeObject? value)
{ {
CheckHandle (); GetCheckedHandle ();
if (DoSetProperty (name, value)) if (DoSetProperty (name, value))
return; return;
throw new InvalidOperationException (string.Format ( throw new InvalidOperationException (string.Format (
@ -596,11 +596,11 @@ namespace CoreFoundation {
} }
} }
public event EventHandler<StreamEventArgs> OpenCompletedEvent; public event EventHandler<StreamEventArgs>? OpenCompletedEvent;
public event EventHandler<StreamEventArgs> HasBytesAvailableEvent; public event EventHandler<StreamEventArgs>? HasBytesAvailableEvent;
public event EventHandler<StreamEventArgs> CanAcceptBytesEvent; public event EventHandler<StreamEventArgs>? CanAcceptBytesEvent;
public event EventHandler<StreamEventArgs> ErrorEvent; public event EventHandler<StreamEventArgs>? ErrorEvent;
public event EventHandler<StreamEventArgs> ClosedEvent; public event EventHandler<StreamEventArgs>? ClosedEvent;
protected virtual void OnOpenCompleted (StreamEventArgs args) protected virtual void OnOpenCompleted (StreamEventArgs args)
{ {
@ -639,9 +639,9 @@ namespace CoreFoundation {
#endregion #endregion
protected abstract void ScheduleWithRunLoop (CFRunLoop loop, NSString mode); protected abstract void ScheduleWithRunLoop (CFRunLoop loop, NSString? mode);
protected abstract void UnscheduleFromRunLoop (CFRunLoop loop, NSString mode); protected abstract void UnscheduleFromRunLoop (CFRunLoop loop, NSString? mode);
protected delegate void CFStreamCallback (IntPtr s, nint type, IntPtr info); protected delegate void CFStreamCallback (IntPtr s, nint type, IntPtr info);
@ -649,7 +649,7 @@ namespace CoreFoundation {
static void OnCallback (IntPtr s, nint type, IntPtr info) static void OnCallback (IntPtr s, nint type, IntPtr info)
{ {
var stream = GCHandle.FromIntPtr (info).Target as CFStream; var stream = GCHandle.FromIntPtr (info).Target as CFStream;
stream.OnCallback ((CFStreamEventType) (long) type); stream?.OnCallback ((CFStreamEventType) (long) type);
} }
static CFStreamCallback OnCallbackDelegate = OnCallback; static CFStreamCallback OnCallbackDelegate = OnCallback;
@ -678,9 +678,9 @@ namespace CoreFoundation {
public void EnableEvents (CFRunLoop runLoop, NSString runLoopMode) public void EnableEvents (CFRunLoop runLoop, NSString runLoopMode)
{ {
if (open || closed || (loop != null)) if (open || closed || (loop is not null))
throw new InvalidOperationException (); throw new InvalidOperationException ();
CheckHandle (); GetCheckedHandle ();
loop = runLoop; loop = runLoop;
loopMode = runLoopMode; loopMode = runLoopMode;
@ -699,7 +699,7 @@ namespace CoreFoundation {
var ptr = Marshal.AllocHGlobal (Marshal.SizeOf (typeof (CFStreamClientContext))); var ptr = Marshal.AllocHGlobal (Marshal.SizeOf (typeof (CFStreamClientContext)));
try { try {
Marshal.StructureToPtr (ctx, ptr, false); Marshal.StructureToPtr (ctx, ptr, false);
if (!DoSetClient (OnCallbackDelegate, (nint) (long) args, ptr)) if (!DoSetClient (OnCallbackDelegate, (CFIndex) (long) args, ptr))
throw new InvalidOperationException ("Stream does not support async events."); throw new InvalidOperationException ("Stream does not support async events.");
} finally { } finally {
Marshal.FreeHGlobal (ptr); Marshal.FreeHGlobal (ptr);
@ -708,46 +708,30 @@ namespace CoreFoundation {
ScheduleWithRunLoop (runLoop, runLoopMode); ScheduleWithRunLoop (runLoop, runLoopMode);
} }
protected abstract bool DoSetClient (CFStreamCallback callback, CFIndex eventTypes, protected abstract bool DoSetClient (CFStreamCallback? callback, CFIndex eventTypes,
IntPtr context); IntPtr context);
protected CFStream (IntPtr handle) #if !XAMCORE_4_0
{ [Obsolete ("Call 'GetCheckedHandle ()' instead.")]
this.handle = handle;
}
protected void CheckHandle () protected void CheckHandle ()
{ {
if (handle == IntPtr.Zero) GetCheckedHandle ();
throw new ObjectDisposedException (GetType ().Name); }
#endif
protected CFStream (IntPtr handle, bool owns)
: base (handle, owns)
{
} }
~CFStream () protected override void Dispose (bool disposing)
{
Dispose (false);
}
public void Dispose ()
{
Dispose (true);
GC.SuppressFinalize (this);
}
public IntPtr Handle {
get { return handle; }
}
protected virtual void Dispose (bool disposing)
{ {
if (disposing) { if (disposing) {
Close (); Close ();
if (gch.IsAllocated) if (gch.IsAllocated)
gch.Free (); gch.Free ();
} }
if (handle != IntPtr.Zero) { base.Dispose (disposing);
CFObject.CFRelease (handle);
handle = IntPtr.Zero;
}
} }
#if !NET #if !NET
@ -779,10 +763,10 @@ namespace CoreFoundation {
#endif #endif
public DispatchQueue ReadDispatchQueue { public DispatchQueue ReadDispatchQueue {
get { get {
return new DispatchQueue (CFReadStreamCopyDispatchQueue (handle)); return new DispatchQueue (CFReadStreamCopyDispatchQueue (Handle));
} }
set { set {
CFReadStreamSetDispatchQueue (handle, value == null ? IntPtr.Zero : value.Handle); CFReadStreamSetDispatchQueue (Handle, value.GetHandle ());
} }
} }
@ -791,10 +775,10 @@ namespace CoreFoundation {
#endif #endif
public DispatchQueue WriteDispatchQueue { public DispatchQueue WriteDispatchQueue {
get { get {
return new DispatchQueue (CFWriteStreamCopyDispatchQueue (handle)); return new DispatchQueue (CFWriteStreamCopyDispatchQueue (Handle));
} }
set { set {
CFWriteStreamSetDispatchQueue (handle, value == null ? IntPtr.Zero : value.Handle); CFWriteStreamSetDispatchQueue (Handle, value.GetHandle ());
} }
} }
} }

Просмотреть файл

@ -27,6 +27,8 @@
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// //
#nullable enable
using System; using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using CoreFoundation; using CoreFoundation;
@ -38,15 +40,15 @@ using CFIndex = System.nint;
namespace CoreFoundation { namespace CoreFoundation {
public class CFWriteStream : CFStream { public class CFWriteStream : CFStream {
internal CFWriteStream (IntPtr handle) internal CFWriteStream (IntPtr handle, bool owns)
: base (handle) : base (handle, owns)
{ {
} }
[DllImport (Constants.CoreFoundationLibrary)] [DllImport (Constants.CoreFoundationLibrary)]
extern static /* CFErrorRef */ IntPtr CFWriteStreamCopyError (/* CFWriteStreamRef */ IntPtr stream); extern static /* CFErrorRef */ IntPtr CFWriteStreamCopyError (/* CFWriteStreamRef */ IntPtr stream);
public override CFException GetError () public override CFException? GetError ()
{ {
var error = CFWriteStreamCopyError (Handle); var error = CFWriteStreamCopyError (Handle);
if (error == IntPtr.Zero) if (error == IntPtr.Zero)
@ -93,16 +95,16 @@ namespace CoreFoundation {
public int Write (byte[] buffer) public int Write (byte[] buffer)
{ {
if (buffer == null) if (buffer is null)
throw new ArgumentNullException ("buffer"); throw new ArgumentNullException (nameof (buffer));
return Write (buffer, 0, buffer.Length); return Write (buffer, 0, buffer.Length);
} }
public unsafe int Write (byte[] buffer, nint offset, nint count) public unsafe int Write (byte[] buffer, nint offset, nint count)
{ {
if (buffer == null) if (buffer is null)
throw new ArgumentNullException ("buffer"); throw new ArgumentNullException (nameof (buffer));
CheckHandle (); GetCheckedHandle ();
if (offset < 0) if (offset < 0)
throw new ArgumentException (); throw new ArgumentException ();
if (count < 1) if (count < 1)
@ -116,35 +118,35 @@ namespace CoreFoundation {
[DllImport (Constants.CoreFoundationLibrary)] [DllImport (Constants.CoreFoundationLibrary)]
[return: MarshalAs (UnmanagedType.I1)] [return: MarshalAs (UnmanagedType.I1)]
static extern /* Boolean */ bool CFWriteStreamSetClient (/* CFWriteStreamRef */ IntPtr stream, /* CFOptionFlags */ nint streamEvents, static extern /* Boolean */ bool CFWriteStreamSetClient (/* CFWriteStreamRef */ IntPtr stream, /* CFOptionFlags */ nint streamEvents,
/* CFWriteStreamClientCallBack */ CFStreamCallback clientCB, /* CFStreamClientContext* */ IntPtr clientContext); /* CFWriteStreamClientCallBack */ CFStreamCallback? clientCB, /* CFStreamClientContext* */ IntPtr clientContext);
protected override bool DoSetClient (CFStreamCallback callback, CFIndex eventTypes, protected override bool DoSetClient (CFStreamCallback? callback, CFIndex eventTypes,
IntPtr context) IntPtr context)
{ {
return CFWriteStreamSetClient (Handle, eventTypes, callback, context); return CFWriteStreamSetClient (Handle, (nint) eventTypes, callback, context);
} }
[DllImport (Constants.CoreFoundationLibrary)] [DllImport (Constants.CoreFoundationLibrary)]
extern static void CFWriteStreamScheduleWithRunLoop (/* CFWriteStreamRef */ IntPtr stream, /* CFRunLoopRef */ IntPtr runLoop, /* CFStringRef */ IntPtr runLoopMode); extern static void CFWriteStreamScheduleWithRunLoop (/* CFWriteStreamRef */ IntPtr stream, /* CFRunLoopRef */ IntPtr runLoop, /* CFStringRef */ IntPtr runLoopMode);
protected override void ScheduleWithRunLoop (CFRunLoop loop, NSString mode) protected override void ScheduleWithRunLoop (CFRunLoop loop, NSString? mode)
{ {
if (loop == null) if (loop is null)
throw new ArgumentNullException ("loop"); throw new ArgumentNullException (nameof (loop));
if (mode == null) if (mode is null)
throw new ArgumentNullException ("mode"); throw new ArgumentNullException (nameof (mode));
CFWriteStreamScheduleWithRunLoop (Handle, loop.Handle, mode.Handle); CFWriteStreamScheduleWithRunLoop (Handle, loop.Handle, mode.Handle);
} }
[DllImport (Constants.CoreFoundationLibrary)] [DllImport (Constants.CoreFoundationLibrary)]
extern static void CFWriteStreamUnscheduleFromRunLoop (/* CFWriteStreamRef */ IntPtr stream, /* CFRunLoopRef */ IntPtr runLoop, /* CFStringRef */ IntPtr runLoopMode); extern static void CFWriteStreamUnscheduleFromRunLoop (/* CFWriteStreamRef */ IntPtr stream, /* CFRunLoopRef */ IntPtr runLoop, /* CFStringRef */ IntPtr runLoopMode);
protected override void UnscheduleFromRunLoop (CFRunLoop loop, NSString mode) protected override void UnscheduleFromRunLoop (CFRunLoop loop, NSString? mode)
{ {
if (loop == null) if (loop is null)
throw new ArgumentNullException ("loop"); throw new ArgumentNullException (nameof (loop));
if (mode == null) if (mode is null)
throw new ArgumentNullException ("mode"); throw new ArgumentNullException (nameof (mode));
CFWriteStreamUnscheduleFromRunLoop (Handle, loop.Handle, mode.Handle); CFWriteStreamUnscheduleFromRunLoop (Handle, loop.Handle, mode.Handle);
} }
@ -153,8 +155,8 @@ namespace CoreFoundation {
protected override IntPtr DoGetProperty (NSString name) protected override IntPtr DoGetProperty (NSString name)
{ {
if (name == null) if (name is null)
throw new ArgumentNullException ("name"); throw new ArgumentNullException (nameof (name));
return CFWriteStreamSetProperty (Handle, name.Handle); return CFWriteStreamSetProperty (Handle, name.Handle);
} }
@ -162,11 +164,11 @@ namespace CoreFoundation {
[return: MarshalAs (UnmanagedType.I1)] [return: MarshalAs (UnmanagedType.I1)]
extern static /* Boolean */ bool CFWriteStreamSetProperty (/* CFWriteStreamRef */ IntPtr stream, /* CFStringRef */ IntPtr propertyName, /* CFTypeRef */ IntPtr value); extern static /* Boolean */ bool CFWriteStreamSetProperty (/* CFWriteStreamRef */ IntPtr stream, /* CFStringRef */ IntPtr propertyName, /* CFTypeRef */ IntPtr value);
protected override bool DoSetProperty (NSString name, INativeObject value) protected override bool DoSetProperty (NSString name, INativeObject? value)
{ {
if (name == null) if (name is null)
throw new ArgumentNullException ("name"); throw new ArgumentNullException (nameof (name));
return CFWriteStreamSetProperty (Handle, name.Handle, value == null ? IntPtr.Zero : value.Handle); return CFWriteStreamSetProperty (Handle, name.Handle, value.GetHandle ());
} }
} }
} }