Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for components defining their own Equals and GetHashCode #1181

Merged
merged 4 commits into from
Apr 29, 2022
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 109 additions & 0 deletions src/Tests/TestComponentCSharp/CustomEquals.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
#include "pch.h"
#include "CustomEquals.h"
#include "CustomEquals.g.cpp"
#include "CustomEquals2.g.cpp"
#include "UnSealedCustomEquals.g.cpp"
#include "DerivedCustomEquals.g.cpp"

namespace winrt::TestComponentCSharp::implementation
{
int32_t CustomEquals::Value()
{
return value;
}

void CustomEquals::Value(int32_t value)
{
this->value = value;
}

// Returns true as long as it is the same type (CustomEquals).
bool CustomEquals::Equals(winrt::Windows::Foundation::IInspectable const& obj)
{
if (obj == nullptr)
{
return false;
}

auto customEqualsObj = obj.try_as<CustomEquals>();
if (customEqualsObj)
{
return true;
}

return false;
}

int32_t CustomEquals::GetHashCode()
{
return 5;
}

// Returns true if Value is the same in both.
bool CustomEquals::Equals(winrt::TestComponentCSharp::CustomEquals const& other)
{
return other != nullptr && Value() == other.Value();
}

int32_t CustomEquals2::Value()
{
return value;
}

void CustomEquals2::Value(int32_t value)
{
this->value = value;
}

int32_t CustomEquals2::Equals(winrt::Windows::Foundation::IInspectable const& obj)
{
return value;
}

int32_t CustomEquals2::Equals(winrt::TestComponentCSharp::CustomEquals2 const& other)
{
return value;
}

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

void UnSealedCustomEquals::Value(int32_t value)
{
this->value = value;
}

int32_t UnSealedCustomEquals::GetHashCode()
{
return 8;
}

bool DerivedCustomEquals::Equals(winrt::Windows::Foundation::IInspectable const& obj)
{
if (obj == nullptr)
{
return false;
}

auto customEqualsObj = obj.try_as<DerivedCustomEquals>();
if (customEqualsObj)
{
return true;
}

return false;
}

int32_t DerivedCustomEquals::GetHashCode()
{
return 10;
}

bool DerivedCustomEquals::Equals(winrt::TestComponentCSharp::UnSealedCustomEquals const& other)
{
return other != nullptr && Value() == other.Value();
}

}
74 changes: 74 additions & 0 deletions src/Tests/TestComponentCSharp/CustomEquals.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#pragma once
#include "CustomEquals.g.h"
#include "CustomEquals2.g.h"
#include "UnSealedCustomEquals.g.h"
#include "DerivedCustomEquals.g.h"

namespace winrt::TestComponentCSharp::implementation
{
struct CustomEquals : CustomEqualsT<CustomEquals>
{
CustomEquals() = default;

int32_t Value();
void Value(int32_t value);
bool Equals(winrt::Windows::Foundation::IInspectable const& obj);
int32_t GetHashCode();
bool Equals(winrt::TestComponentCSharp::CustomEquals const& other);

private:
int32_t value;
};

struct CustomEquals2 : CustomEquals2T<CustomEquals2>
{
CustomEquals2() = default;

int32_t Value();
void Value(int32_t value);
int32_t Equals(winrt::Windows::Foundation::IInspectable const& obj);
int32_t Equals(winrt::TestComponentCSharp::CustomEquals2 const& other);

private:
int32_t value;
};

struct UnSealedCustomEquals : UnSealedCustomEqualsT<UnSealedCustomEquals>
{
UnSealedCustomEquals() = default;

int32_t Value();
void Value(int32_t value);
int32_t GetHashCode();

private:
int32_t value;
};

struct DerivedCustomEquals : DerivedCustomEqualsT<DerivedCustomEquals, TestComponentCSharp::implementation::UnSealedCustomEquals>
{
DerivedCustomEquals() = default;

bool Equals(winrt::Windows::Foundation::IInspectable const& obj);
int32_t GetHashCode();
bool Equals(winrt::TestComponentCSharp::UnSealedCustomEquals const& other);
};
}
namespace winrt::TestComponentCSharp::factory_implementation
{
struct CustomEquals : CustomEqualsT<CustomEquals, implementation::CustomEquals>
{
};

struct CustomEquals2 : CustomEquals2T<CustomEquals2, implementation::CustomEquals2>
{
};

struct UnSealedCustomEquals : UnSealedCustomEqualsT<UnSealedCustomEquals, implementation::UnSealedCustomEquals>
{
};

struct DerivedCustomEquals : DerivedCustomEqualsT<DerivedCustomEquals, implementation::DerivedCustomEquals>
{
};
}
42 changes: 42 additions & 0 deletions src/Tests/TestComponentCSharp/TestComponentCSharp.idl
Original file line number Diff line number Diff line change
Expand Up @@ -548,6 +548,48 @@ And this is another one"
void f();
}

[default_interface]
runtimeclass CustomEquals
{
Int32 Value{ get; set; };

CustomEquals();
[default_overload]
Boolean Equals(Object obj);
Int32 GetHashCode();
Boolean Equals(CustomEquals other);
}

[default_interface]
runtimeclass CustomEquals2
{
Int32 Value{ get; set; };

CustomEquals2();
[default_overload]
Int32 Equals(Object obj);
Int32 Equals(CustomEquals2 other);
}

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

UnSealedCustomEquals();
Int32 GetHashCode();
}

[default_interface]
runtimeclass DerivedCustomEquals : UnSealedCustomEquals
{
DerivedCustomEquals();
[default_overload]
Boolean Equals(Object obj);
Int32 GetHashCode();
Boolean Equals(UnSealedCustomEquals other);
}

// Compile time test for sub windows namespace
namespace Windows
{
Expand Down
2 changes: 2 additions & 0 deletions src/Tests/TestComponentCSharp/TestComponentCSharp.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
<ItemGroup>
<ClInclude Include="ABCDEFGHIJKLMNOPQRSTUVQXYZabcdefghijklmnopqrstuvqxyzABCDEFGHIJKLMNOPQRSTUVQXYZabcdefghijklmnopqrstuvqxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.h" />
<ClInclude Include="AnotherAssembly.SetPropertyClass.h" />
<ClInclude Include="CustomEquals.h" />
<ClInclude Include="ManualProjectionTestClasses.h" />
<ClInclude Include="pch.h" />
<ClInclude Include="Class.h">
Expand All @@ -93,6 +94,7 @@
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
<ClCompile Include="ABCDEFGHIJKLMNOPQRSTUVQXYZabcdefghijklmnopqrstuvqxyzABCDEFGHIJKLMNOPQRSTUVQXYZabcdefghijklmnopqrstuvqxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.cpp" />
<ClCompile Include="AnotherAssembly.SetPropertyClass.cpp" />
<ClCompile Include="CustomEquals.cpp" />
<ClCompile Include="pch.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
<ClCompile Include="Windows.Class.cpp" />
<ClCompile Include="ABCDEFGHIJKLMNOPQRSTUVQXYZabcdefghijklmnopqrstuvqxyzABCDEFGHIJKLMNOPQRSTUVQXYZabcdefghijklmnopqrstuvqxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.cpp" />
<ClCompile Include="AnotherAssembly.SetPropertyClass.cpp" />
<ClCompile Include="CustomEquals.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="pch.h" />
Expand All @@ -31,6 +32,7 @@
<ClInclude Include="Windows.Class.h" />
<ClInclude Include="ABCDEFGHIJKLMNOPQRSTUVQXYZabcdefghijklmnopqrstuvqxyzABCDEFGHIJKLMNOPQRSTUVQXYZabcdefghijklmnopqrstuvqxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.h" />
<ClInclude Include="AnotherAssembly.SetPropertyClass.h" />
<ClInclude Include="CustomEquals.h" />
</ItemGroup>
<ItemGroup>
<Midl Include="TestComponentCSharp.idl" />
Expand Down
61 changes: 59 additions & 2 deletions src/Tests/UnitTest/TestComponentCSharp_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2798,8 +2798,8 @@ private async Task TestPnpPropertiesAsync()
}
return pnpObject;
}).ToList();
}

}
#if NET
[TestComponentCSharp.Warning] // NO warning CA1416
class WarningManaged { };
Expand Down Expand Up @@ -2848,5 +2848,62 @@ private void TestSupportedOSPlatformWarnings()
WarningStatic.WarningEvent += (object s, Int32 v) => { }; // warning CA1416
}
#endif

[Fact]
public void TestObjectFunctions()
{
CustomEquals first = new()
{
Value = 2
};
CustomEquals second = new()
{
Value = 4
};
CustomEquals third = new()
{
Value = 2
};

Assert.False(first.Equals(second));
Assert.True(first.Equals(third));
Assert.True(first.Equals(first));
Assert.True(Object.Equals(first, second));
Assert.True(Object.Equals(second, third));
Assert.Equal(5, first.GetHashCode());
Assert.Equal(5, second.GetHashCode());

Class fourth = new();
Class fifth = new();
Assert.True(fourth.Equals(fourth));
Assert.False(fourth.Equals(fifth));
Assert.False(Object.Equals(fourth, fifth));
Assert.True(Object.Equals(fifth, fifth));
fourth.GetHashCode();

CustomEquals2 sixth = new()
{
Value = 4
};
Assert.Equal(4, sixth.Equals(sixth));
Assert.Equal(4, sixth.Equals(fifth));
Assert.False(object.Equals(sixth, fifth));
Assert.True(object.Equals(sixth, sixth));
Assert.False(((IEquatable<CustomEquals2>)sixth).Equals(new CustomEquals2()));
Assert.True(((IEquatable<CustomEquals2>)sixth).Equals(sixth));

UnSealedCustomEquals seventh = new()
{
Value = 2
};
DerivedCustomEquals eighth = new()
{
Value = 2
};
Assert.Equal(10, eighth.GetHashCode());
// Uses Equals defined on derived.
Assert.True(eighth.Equals(seventh));
Assert.False(seventh.Equals(eighth));
}
}
}
Loading