Skip to content

Commit

Permalink
Improve exception messages for failed casts (#1826)
Browse files Browse the repository at this point in the history
  • Loading branch information
Sergio0694 authored Oct 15, 2024
1 parent ce2ef94 commit 938d95f
Showing 1 changed file with 29 additions and 9 deletions.
38 changes: 29 additions & 9 deletions src/WinRT.Runtime/CastExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
// Licensed under the MIT License.

using System;
#if !NET
using System.Reflection;
#endif
using System.Runtime.CompilerServices;
using WinRT.Interop;

namespace WinRT
Expand All @@ -28,9 +31,11 @@ static class CastExtensions
/// <exception cref="ArgumentException">Thrown if the runtime type of <paramref name="value"/> is not a projected type (if the object is a managed object).</exception>
public static TInterface As<TInterface>(this object value)
{
IObjectReference objRef;

if (typeof(TInterface) == typeof(object))
{
if (TryGetRefForObject(value, allowComposed: false, out IObjectReference objRef))
if (TryGetRefForObject(value, allowComposed: false, out objRef))
{
using (objRef)
{
Expand All @@ -44,10 +49,31 @@ public static TInterface As<TInterface>(this object value)
return convertableInMetadata;
}

using (var objRef = GetRefForObject(value))
if (TryGetRefForObject(value, allowComposed: true, out objRef))
{
using (objRef)
{
return objRef.AsInterface<TInterface>();
}
}

// Shared helper to get an exception with a helpful message, that we can efficiently throw
[MethodImpl(MethodImplOptions.NoInlining)]
static Exception GetArgumentExceptionForFailedCast(object value)
{
return objRef.AsInterface<TInterface>();
if (value is null)
{
return new ArgumentNullException(
paramName: nameof(value),
message: $"The source object being cast to type '{typeof(TInterface)}' is 'null'.");
}

return new ArgumentException(
paramName: nameof(value),
message: $"The source object type ('{value.GetType()}') being cast to type '{typeof(TInterface)}' is not a projected type, nor does it inherit from a projected type.");
}

throw GetArgumentExceptionForFailedCast(value);
}

/// <summary>
Expand Down Expand Up @@ -102,12 +128,6 @@ private static bool TryGetRefForObject(object value, bool allowComposed, out IOb
reference = null;
return false;
}

private static IObjectReference GetRefForObject(object value)
{
return TryGetRefForObject(value, allowComposed: true, out var objRef) ? objRef
: throw new ArgumentException("Source object type is not a projected type and does not inherit from a projected type.", nameof(value));
}

private static bool TryGetComposedRefForQI(object value, out IObjectReference objRef)
{
Expand Down

0 comments on commit 938d95f

Please sign in to comment.