fixes EETypeLoadException issue: export class DelegateCommand (#18)

* fixes EETypeLoadException issue: export class DelegateCommand

* weak-reference in C++/CX

* WeakRef in C# codebase

* UTF-8-BOM

* spaces in macro

* resolve some comments from the offline review

* format

* rename file
This commit is contained in:
Tian L 2021-04-22 14:07:24 +08:00 committed by GitHub
commit b53600bfc4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 78 additions and 73 deletions

View file

@ -7,18 +7,14 @@ namespace CalculatorApp
{
namespace Common
{
template <typename TTarget>
ref class DelegateCommand : public Windows::UI::Xaml::Input::ICommand
public delegate void DelegateCommandHandler(Platform::Object ^ parameter);
public ref class DelegateCommand sealed : public Windows::UI::Xaml::Input::ICommand
{
internal :
typedef void (TTarget::*CommandHandlerFunc)(Platform::Object ^);
DelegateCommand(TTarget ^ target, CommandHandlerFunc func)
: m_weakTarget(target)
, m_function(func)
{
}
public:
DelegateCommand(DelegateCommandHandler ^ handler)
: m_handler(handler)
{}
private:
// Explicit, and private, implementation of ICommand, this way of programming makes it so
@ -27,11 +23,7 @@ namespace CalculatorApp
// code in the app calling Execute.
virtual void ExecuteImpl(Platform::Object ^ parameter) sealed = Windows::UI::Xaml::Input::ICommand::Execute
{
TTarget ^ target = m_weakTarget.Resolve<TTarget>();
if (target)
{
(target->*m_function)(parameter);
}
m_handler->Invoke(parameter);
}
virtual bool CanExecuteImpl(Platform::Object ^ parameter) sealed = Windows::UI::Xaml::Input::ICommand::CanExecute
@ -39,9 +31,9 @@ namespace CalculatorApp
return true;
}
virtual event Windows::Foundation::EventHandler<Platform::Object^>^ CanExecuteChangedImpl
virtual event Windows::Foundation::EventHandler<Platform::Object ^> ^ CanExecuteChangedImpl
{
virtual Windows::Foundation::EventRegistrationToken add(Windows::Foundation::EventHandler<Platform::Object^>^ handler) sealed = Windows::UI::Xaml::Input::ICommand::CanExecuteChanged::add
virtual Windows::Foundation::EventRegistrationToken add(Windows::Foundation::EventHandler<Platform::Object ^> ^ handler) sealed = Windows::UI::Xaml::Input::ICommand::CanExecuteChanged::add
{
return m_canExecuteChanged += handler;
}
@ -52,17 +44,25 @@ namespace CalculatorApp
}
private:
DelegateCommandHandler ^ m_handler;
event Windows::Foundation::EventHandler<Platform::Object^>^ m_canExecuteChanged;
CommandHandlerFunc m_function;
Platform::WeakReference m_weakTarget;
event Windows::Foundation::EventHandler<Platform::Object ^> ^ m_canExecuteChanged;
};
template <typename TTarget, typename TFuncPtr>
DelegateCommand<TTarget> ^ MakeDelegate(TTarget ^ target, TFuncPtr&& function) {
return ref new DelegateCommand<TTarget>(target, std::forward<TFuncPtr>(function));
}
DelegateCommandHandler ^ MakeDelegateCommandHandler(TTarget ^ target, TFuncPtr&& function)
{
Platform::WeakReference weakTarget(target);
return ref new DelegateCommandHandler([weakTarget, function=std::forward<TFuncPtr>(function)](Platform::Object ^ param)
{
TTarget ^ thatTarget = weakTarget.Resolve<TTarget>();
if (nullptr != thatTarget)
{
(thatTarget->*function)(param);
}
}
);
}
}
}

View file

@ -168,11 +168,22 @@ public:
// The variable member generated by this macro should not be used in the class code, use the
// property getter instead.
#define COMMAND_FOR_METHOD(p, m) \
property Windows::UI::Xaml::Input::ICommand^ p {\
Windows::UI::Xaml::Input::ICommand^ get() {\
if (!donotuse_##p) {\
donotuse_##p = CalculatorApp::Common::MakeDelegate(this, &m);\
} return donotuse_##p; }} private: Windows::UI::Xaml::Input::ICommand^ donotuse_##p; \
property Windows::UI::Xaml::Input::ICommand ^ p \
{ \
Windows::UI::Xaml::Input::ICommand ^ get() \
{ \
if (!donotuse_##p) \
{ \
donotuse_##p = ref new CalculatorApp::Common::DelegateCommand( \
CalculatorApp::Common::MakeDelegateCommandHandler(this, &m) \
); \
} \
return donotuse_##p; \
} \
} \
\
private: \
Windows::UI::Xaml::Input::ICommand ^ donotuse_##p; \
\
public:

View file

@ -151,11 +151,11 @@
<Compile Include="Converters\ItemSizeToVisibilityConverter.cs" />
<Compile Include="Converters\RadixToStringConverter.cs" />
<Compile Include="Converters\VisibilityNegationConverter.cs" />
<Compile Include="DelegateCommand.cs" />
<Compile Include="EquationStylePanelControl.xaml.cs">
<DependentUpon>EquationStylePanelControl.xaml</DependentUpon>
</Compile>
<Compile Include="KeyGraphFeaturesTemplateSelector.cs" />
<Compile Include="Utils\DelegateCommandUtils.cs" />
<Compile Include="Views\Calculator.xaml.cs">
<DependentUpon>Calculator.xaml</DependentUpon>
</Compile>

View file

@ -1,35 +0,0 @@
using System;
namespace CalculatorApp.Common
{
internal class DelegateCommand<TTarget> : System.Windows.Input.ICommand
{
public delegate void CommandHandlerFunc(object obj);
public DelegateCommand(TTarget target, CommandHandlerFunc func)
{
m_weakTarget = new WeakReference(target);
m_function = func;
}
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
object target = m_weakTarget.Target;
if (target != null && target is TTarget)
{
m_function(parameter);
}
}
private CommandHandlerFunc m_function;
private WeakReference m_weakTarget;
}
}

View file

@ -0,0 +1,26 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using CalculatorApp.Common;
namespace CalculatorApp.Utils
{
static class DelegateCommandUtils
{
public static DelegateCommand MakeDelegateCommand<TTarget>(TTarget target, DelegateCommandHandler handler)
where TTarget : class
{
WeakReference weakTarget = new WeakReference(target);
return new DelegateCommand(param =>
{
TTarget thatTarget = weakTarget.Target as TTarget;
if(null != thatTarget)
{
handler.Invoke(param);
}
});
}
}
}

View file

@ -9,6 +9,7 @@ using CalculatorApp;
using CalculatorApp.Common;
using CalculatorApp.Converters;
using CalculatorApp.Controls;
using CalculatorApp.Utils;
using CalculatorApp.ViewModel;
using Windows.Foundation;
@ -140,7 +141,7 @@ namespace CalculatorApp
{
if (donotuse_HistoryButtonPressed == null)
{
donotuse_HistoryButtonPressed = new DelegateCommand<Calculator>(this, ToggleHistoryFlyout);
donotuse_HistoryButtonPressed = DelegateCommandUtils.MakeDelegateCommand(this, ToggleHistoryFlyout);
}
return donotuse_HistoryButtonPressed;
}

View file

@ -11,6 +11,7 @@ using System.Collections.Generic;
using System.Threading.Tasks;
using System.Diagnostics;
using CalculatorApp;
using CalculatorApp.Utils;
using CalculatorApp.ViewModel;
using Windows.Foundation;
@ -47,7 +48,7 @@ namespace CalculatorApp
{
if (donotuse_ButtonPressed == null)
{
donotuse_ButtonPressed = new CalculatorApp.Common.DelegateCommand<CalculatorScientificAngleButtons>(this, OnAngleButtonPressed);
donotuse_ButtonPressed = DelegateCommandUtils.MakeDelegateCommand(this, OnAngleButtonPressed);
}
return donotuse_ButtonPressed;
}

View file

@ -9,6 +9,7 @@ using CalculatorApp;
using CalculatorApp.Common;
using CalculatorApp.Common.Automation;
using CalculatorApp.Controls;
using CalculatorApp.Utils;
using CalculatorApp.ViewModel;
//using CalcManager.NumberFormattingUtils;
using GraphControl;
@ -114,7 +115,7 @@ namespace CalculatorApp
{
if (donotuse_ZoomOutButtonPressed == null)
{
donotuse_ZoomOutButtonPressed = new DelegateCommand<GraphingCalculator>(this, OnZoomOutCommand);
donotuse_ZoomOutButtonPressed = DelegateCommandUtils.MakeDelegateCommand(this, OnZoomOutCommand);
}
return donotuse_ZoomOutButtonPressed;
}
@ -127,7 +128,7 @@ namespace CalculatorApp
{
if (donotuse_ZoomInButtonPressed == null)
{
donotuse_ZoomInButtonPressed = new DelegateCommand<GraphingCalculator>(this, OnZoomInCommand);
donotuse_ZoomInButtonPressed = DelegateCommandUtils.MakeDelegateCommand(this, OnZoomInCommand);
}
return donotuse_ZoomInButtonPressed;
}

View file

@ -2,6 +2,7 @@
using System.Windows.Input;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using CalculatorApp.Utils;
// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236
@ -16,8 +17,7 @@ namespace CalculatorApp
{
if (donotuse_BitLengthButtonPressed == null)
{
donotuse_BitLengthButtonPressed =
new Common.DelegateCommand<CalculatorProgrammerDisplayPanel>(this, OnBitLengthButtonPressed);
donotuse_BitLengthButtonPressed = DelegateCommandUtils.MakeDelegateCommand(this, OnBitLengthButtonPressed);
}
return donotuse_BitLengthButtonPressed;
}