Skip to content
Merged
6 changes: 6 additions & 0 deletions src/Tests/TestComponentCSharp/Class.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "pch.h"
#include "Class.h"
#include "Class.g.cpp"
#include "CustomEquals.h"

using namespace std::chrono;

Expand Down Expand Up @@ -2121,5 +2122,10 @@ namespace winrt::TestComponentCSharp::implementation

return winrt::make<bad_runtime_classname>();
}

winrt::TestComponentCSharp::UnSealedCustomEquals Class::NonProjectedClassInstance()
{
return winrt::make<NonProjectedDerivedCustomEquals>();
}
}

1 change: 1 addition & 0 deletions src/Tests/TestComponentCSharp/Class.h
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,7 @@ namespace winrt::TestComponentCSharp::implementation
void RaiseCanExecuteChanged();

static Windows::Foundation::IInspectable BadRuntimeClassName();
static winrt::TestComponentCSharp::UnSealedCustomEquals NonProjectedClassInstance();
};
}

Expand Down
2 changes: 1 addition & 1 deletion src/Tests/TestComponentCSharp/CustomEquals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ namespace winrt::TestComponentCSharp::implementation

int32_t UnSealedCustomEquals::Value()
{
return value;
return value * factor;
}

void UnSealedCustomEquals::Value(int32_t value)
Expand Down
15 changes: 15 additions & 0 deletions src/Tests/TestComponentCSharp/CustomEquals.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ namespace winrt::TestComponentCSharp::implementation
int32_t Value();
void Value(int32_t value);
int32_t GetHashCode();
protected:
int32_t factor = 1;

private:
int32_t value;
Expand All @@ -53,6 +55,19 @@ namespace winrt::TestComponentCSharp::implementation
int32_t GetHashCode();
bool Equals(winrt::TestComponentCSharp::UnSealedCustomEquals const& other);
};

struct NonProjectedDerivedCustomEquals : winrt::implements<NonProjectedDerivedCustomEquals, TestComponentCSharp::implementation::UnSealedCustomEquals>
{
NonProjectedDerivedCustomEquals()
{
factor = 2;
}

hstring GetRuntimeClassName() const override
{
return L"TestComponentCSharp.NonProjectedDerivedCustomEquals";
}
};
}
namespace winrt::TestComponentCSharp::factory_implementation
{
Expand Down
19 changes: 10 additions & 9 deletions src/Tests/TestComponentCSharp/TestComponentCSharp.idl
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,15 @@ namespace TestComponentCSharp
static ISingleton Instance;
}

[default_interface]
unsealed runtimeclass UnSealedCustomEquals
{
Int32 Value{ get; set; };

UnSealedCustomEquals();
Int32 GetHashCode();
}

[default_interface, gc_pressure(Windows.Foundation.Metadata.GCPressureAmount.High)]
runtimeclass Class :
Windows.Foundation.IStringable
Expand Down Expand Up @@ -496,6 +505,7 @@ namespace TestComponentCSharp
void RaiseCanExecuteChanged();

static Object BadRuntimeClassName{ get; };
static UnSealedCustomEquals NonProjectedClassInstance{ get; };
}

runtimeclass ABCDEFGHIJKLMNOPQRSTUVQXYZabcdefghijklmnopqrstuvqxyzABCDEFGHIJKLMNOPQRSTUVQXYZabcdefghijklmnopqrstuvqxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
Expand Down Expand Up @@ -675,15 +685,6 @@ And this is another one"
Int32 Equals(CustomEquals2 other);
}

[default_interface]
unsealed runtimeclass UnSealedCustomEquals
{
Int32 Value{ get; set; };

UnSealedCustomEquals();
Int32 GetHashCode();
}

[default_interface]
runtimeclass DerivedCustomEquals : UnSealedCustomEquals
{
Expand Down
9 changes: 9 additions & 0 deletions src/Tests/UnitTest/TestComponentCSharp_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3897,5 +3897,14 @@ public void TestTimeSpanDictionary()
Assert.Equal(TimeSpan.FromMinutes(1), entries.Value - entries.Key);
}
}

[Fact]
public void TestNontProjectedClassAsBaseClass()
{
UnSealedCustomEquals customEquals = Class.NonProjectedClassInstance;
customEquals.Value = 3;
// Non projected class changes the behavior of the Value property to double it.
Assert.Equal(6, customEquals.Value);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,36 @@ private static void ComWrappersCallback(
{ Ret }
}
};

// Define the 'CreateObject' method as follows:
//
// public static object CreateObject(void* value, out CreatedWrapperFlags wrapperFlags)
MethodDefinition createObjectMethod = new(
name: "CreateObject"u8,
attributes: MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Static,
signature: MethodSignature.CreateStatic(
returnType: module.CorLibTypeFactory.Object,
parameterTypes: [
module.CorLibTypeFactory.Void.MakePointerType(),
interopReferences.CreatedWrapperFlags.Import(module).MakeByReferenceType()]))
{
CilOutParameterIndices = [2],
CilInstructions =
{
// Create the 'WindowsRuntimeObjectReference' instance and use it to create a 'NativeObject' instance
{ Ldarg_0 },
{ Call, get_IidMethod },
{ Ldarg_1 },
{ Call, interopReferences.WindowsRuntimeComWrappersMarshalCreateObjectReferenceUnsafe.Import(module) },
{ Newobj, nativeObjectType.GetMethod(".ctor"u8) },
{ Ret }
}
};

// Add and implement 'CreateObject'
callbackType.AddMethodImplementation(
declaration: interopReferences.IWindowsRuntimeUnsealedObjectComWrappersCallbackCreateObject.Import(module),
method: createObjectMethod);
}

/// <summary>
Expand Down
10 changes: 10 additions & 0 deletions src/WinRT.Interop.Generator/References/InteropReferences.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2047,6 +2047,16 @@ public InteropReferences(
_corLibTypeFactory.Object.MakeByReferenceType(),
CreatedWrapperFlags.ToValueTypeSignature().MakeByReferenceType()]));

/// <summary>
/// Gets the <see cref="MemberReference"/> for <c>WindowsRuntime.InteropServices.IWindowsRuntimeUnsealedObjectComWrappersCallback.CreateObject</c>.
/// </summary>
public MemberReference IWindowsRuntimeUnsealedObjectComWrappersCallbackCreateObject => field ??= IWindowsRuntimeUnsealedObjectComWrappersCallback
.CreateMemberReference("CreateObject"u8, MethodSignature.CreateStatic(
returnType: _corLibTypeFactory.Object,
parameterTypes: [
_corLibTypeFactory.Void.MakePointerType(),
CreatedWrapperFlags.ToValueTypeSignature().MakeByReferenceType()]));

/// <summary>
/// Gets the <see cref="MemberReference"/> for <c>WindowsRuntime.InteropServices.IWindowsRuntimeArrayComWrappersCallback.CreateArray</c>.
/// </summary>
Expand Down
11 changes: 11 additions & 0 deletions src/WinRT.Runtime2/ABI/System/Collections/IEnumerable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,17 @@ public static unsafe bool TryCreateObject(

return false;
}

/// <inheritdoc/>
public static unsafe object CreateObject(void* value, out CreatedWrapperFlags wrapperFlags)
{
WindowsRuntimeObjectReference valueReference = WindowsRuntimeComWrappersMarshal.CreateObjectReferenceUnsafe(
externalComObject: value,
iid: in WellKnownWindowsInterfaceIIDs.IID_IBindableIterable,
wrapperFlags: out wrapperFlags);

return new WindowsRuntimeEnumerable(valueReference);
}
}

/// <summary>
Expand Down
11 changes: 11 additions & 0 deletions src/WinRT.Runtime2/ABI/System/Collections/IEnumerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,17 @@ public static unsafe bool TryCreateObject(

return false;
}

/// <inheritdoc/>
public static unsafe object CreateObject(void* value, out CreatedWrapperFlags wrapperFlags)
{
WindowsRuntimeObjectReference valueReference = WindowsRuntimeComWrappersMarshal.CreateObjectReferenceUnsafe(
externalComObject: value,
iid: in WellKnownWindowsInterfaceIIDs.IID_IBindableIterator,
wrapperFlags: out wrapperFlags);

return new WindowsRuntimeEnumerator(valueReference);
}
}

/// <summary>
Expand Down
11 changes: 11 additions & 0 deletions src/WinRT.Runtime2/ABI/System/Collections/IList.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,17 @@ public static unsafe bool TryCreateObject(

return false;
}

/// <inheritdoc/>
public static unsafe object CreateObject(void* value, out CreatedWrapperFlags wrapperFlags)
{
WindowsRuntimeObjectReference valueReference = WindowsRuntimeComWrappersMarshal.CreateObjectReferenceUnsafe(
externalComObject: value,
iid: in WellKnownWindowsInterfaceIIDs.IID_IBindableVector,
wrapperFlags: out wrapperFlags);

return new WindowsRuntimeList(valueReference);
}
}

/// <summary>
Expand Down
11 changes: 11 additions & 0 deletions src/WinRT.Runtime2/ABI/Windows.Foundation/IAsyncAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,17 @@ public static bool TryCreateObject(

return false;
}

/// <inheritdoc/>
public static object CreateObject(void* value, out CreatedWrapperFlags wrapperFlags)
{
WindowsRuntimeObjectReference objectReference = WindowsRuntimeComWrappersMarshal.CreateObjectReferenceUnsafe(
externalComObject: value,
iid: in WellKnownWindowsInterfaceIIDs.IID_IAsyncAction,
wrapperFlags: out wrapperFlags);

return new WindowsRuntimeAsyncAction(objectReference);
}
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,18 @@ static abstract bool TryCreateObject(
ReadOnlySpan<char> runtimeClassName,
[NotNullWhen(true)] out object? wrapperObject,
out CreatedWrapperFlags wrapperFlags);

/// <summary>
/// Creates a managed Windows Runtime object for a given native object.
/// </summary>
/// <param name="value">The input native object to marshal.</param>
/// <param name="wrapperFlags">Flags used to describe the created wrapper object.</param>
/// <returns>The resulting managed Windows Runtime object.</returns>
/// <remarks>
/// This method is equivalent to <see cref="IWindowsRuntimeObjectComWrappersCallback.CreateObject"/>, but for unsealed
/// types, and is called if <see cref="TryCreateObject"/> failed but not other more specific RCW type could be resolved.
/// Additionally, it can also be called if <see cref="IInspectableVftbl.GetRuntimeClassNameUnsafe"/> fails for any reason.
/// </remarks>
/// <seealso cref="IWindowsRuntimeObjectComWrappersCallback.CreateObject"/>
static abstract object CreateObject(void* value, out CreatedWrapperFlags wrapperFlags);
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ public abstract bool TryCreateObject(
ReadOnlySpan<char> runtimeClassName,
[NotNullWhen(true)] out object? wrapperObject,
out CreatedWrapperFlags wrapperFlags);

/// <inheritdoc cref="IWindowsRuntimeUnsealedObjectComWrappersCallback.CreateObject"/>
public abstract object CreateObject(void* value, out CreatedWrapperFlags wrapperFlags);
}

/// <summary>
Expand All @@ -52,4 +55,10 @@ public override unsafe bool TryCreateObject(
{
return TCallback.TryCreateObject(value, runtimeClassName, out wrapperObject, out wrapperFlags);
}

/// <inheritdoc/>
public override unsafe object CreateObject(void* value, out CreatedWrapperFlags wrapperFlags)
{
return TCallback.CreateObject(value, out wrapperFlags);
}
}
Loading