using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows;
using System.Reflection;
using System.Collections.ObjectModel;
using System.Windows.Input;
using System.Threading;
using System.Windows.Threading;
namespace ObjectPresentation
{
public class MethodPresenter : Control
{
#region Properties
#region MethodInformation
public MethodInfo MethodInformation
{
get { return (MethodInfo)GetValue(MethodInformationProperty); }
set { SetValue(MethodInformationProperty, value); }
}
public static readonly DependencyProperty MethodInformationProperty =
DependencyProperty.Register("MethodInformation", typeof(MethodInfo), typeof(MethodPresenter), new UIPropertyMetadata(null, OnMethodInformationChanged));
private static void OnMethodInformationChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
MethodPresenter mp = sender as MethodPresenter;
if (mp == null)
{
return;
}
mp.MethodParameters.Clear();
if (mp.MethodInformation != null)
{
mp.MethodName = mp.MethodInformation.Name;
mp.MethodInformation.GetParameters().ToList().
ForEach(pi => mp.MethodParameters.Add(
new ParameterInputValueViewModel(pi)
{
KnownTypes = mp.KnownTypes,
AutoGenerateCompatibleTypes = mp.AutoGenerateCompatibleTypes,
DataTemplates = mp.DataTemplates
}));
}
else
{
mp.MethodName = null;
}
}
#endregion
#region ObjectInstance
public object ObjectInstance
{
get { return (object)GetValue(ObjectInstanceProperty); }
set { SetValue(ObjectInstanceProperty, value); }
}
public static readonly DependencyProperty ObjectInstanceProperty =
DependencyProperty.Register("ObjectInstance", typeof(object), typeof(MethodPresenter), new UIPropertyMetadata(null));
#endregion
#region MethodName
public string MethodName
{
get { return (string)GetValue(MethodNameProperty); }
protected set { SetValue(MethodNameProperty, value); }
}
public static readonly DependencyProperty MethodNameProperty =
DependencyProperty.Register("MethodName", typeof(string), typeof(MethodPresenter), new UIPropertyMetadata(null));
#endregion
#region MethodParameters
private ObservableCollection<InputValueViewModel> _methodParameters;
public ObservableCollection<InputValueViewModel> MethodParameters
{
get { return _methodParameters ?? (_methodParameters = new ObservableCollection<InputValueViewModel>()); }
}
#endregion
#region MethodResults
private ObservableCollection<MethodResultViewModel> _methodResults;
public ObservableCollection<MethodResultViewModel> MethodResults
{
get { return _methodResults ?? (_methodResults = new ObservableCollection<MethodResultViewModel>()); }
}
#endregion
#region CurrentMethodResult
public MethodResultViewModel CurrentMethodResult
{
get { return (MethodResultViewModel)GetValue(CurrentMethodResultProperty); }
set { SetValue(CurrentMethodResultProperty, value); }
}
public static readonly DependencyProperty CurrentMethodResultProperty =
DependencyProperty.Register("CurrentMethodResult", typeof(MethodResultViewModel), typeof(MethodPresenter), new UIPropertyMetadata(null));
#endregion
#region HasResults
public bool HasResults
{
get { return (bool)GetValue(HasResultsProperty); }
protected set { SetValue(HasResultsProperty, value); }
}
public static readonly DependencyProperty HasResultsProperty =
DependencyProperty.Register("HasResults", typeof(bool), typeof(MethodPresenter), new UIPropertyMetadata(false));
#endregion
#region IsInvoking
public bool IsInvoking
{
get { return (bool)GetValue(IsInvokingProperty); }
protected set { SetValue(IsInvokingProperty, value); }
}
public static readonly DependencyProperty IsInvokingProperty =
DependencyProperty.Register("IsInvoking", typeof(bool), typeof(MethodPresenter), new UIPropertyMetadata(false));
#endregion
#region StoreMethodResults
public bool StoreMethodResults
{
get { return (bool)GetValue(StoreMethodResultsProperty); }
set { SetValue(StoreMethodResultsProperty, value); }
}
public static readonly DependencyProperty StoreMethodResultsProperty =
DependencyProperty.Register("StoreMethodResults", typeof(bool), typeof(MethodPresenter), new UIPropertyMetadata(false));
#endregion
#region KnownTypes
public IEnumerable<Type> KnownTypes
{
get { return (IEnumerable<Type>)GetValue(KnownTypesProperty); }
set { SetValue(KnownTypesProperty, value); }
}
public static readonly DependencyProperty KnownTypesProperty =
DependencyProperty.Register("KnownTypes", typeof(IEnumerable<Type>), typeof(MethodPresenter), new UIPropertyMetadata(null, OnKnownTypesChanged));
private static void OnKnownTypesChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
MethodPresenter mp = sender as MethodPresenter;
if (mp == null)
{
return;
}
foreach (InputValueViewModel ivvm in mp.MethodParameters)
{
ivvm.KnownTypes = mp.KnownTypes;
}
}
#endregion
#region AutoGenerateCompatibleTypes
public bool AutoGenerateCompatibleTypes
{
get { return (bool)GetValue(AutoGenerateCompatibleTypesProperty); }
set { SetValue(AutoGenerateCompatibleTypesProperty, value); }
}
public static readonly DependencyProperty AutoGenerateCompatibleTypesProperty =
DependencyProperty.Register("AutoGenerateCompatibleTypes", typeof(bool), typeof(MethodPresenter), new UIPropertyMetadata(true, OnAutoGenerateCompatibleTypesChanged));
private static void OnAutoGenerateCompatibleTypesChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
MethodPresenter mp = sender as MethodPresenter;
if (mp == null)
{
return;
}
foreach (InputValueViewModel ivvm in mp.MethodParameters)
{
ivvm.AutoGenerateCompatibleTypes = mp.AutoGenerateCompatibleTypes;
}
}
#endregion
#region DataTemplates
public IEnumerable<TypeDataTemplate> DataTemplates
{
get { return (IEnumerable<TypeDataTemplate>)GetValue(DataTemplatesProperty); }
set { SetValue(DataTemplatesProperty, value); }
}
public static readonly DependencyProperty DataTemplatesProperty =
DependencyProperty.Register("DataTemplates", typeof(IEnumerable<TypeDataTemplate>), typeof(MethodPresenter), new UIPropertyMetadata(null, OnDataTemplatesChanged));
private static void OnDataTemplatesChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
MethodPresenter mp = sender as MethodPresenter;
if (mp == null)
{
return;
}
foreach (InputValueViewModel ivvm in mp.MethodParameters)
{
ivvm.DataTemplates = mp.DataTemplates;
}
}
#endregion
#endregion
#region Events
#region MethodInvokeRequested
public static readonly RoutedEvent MethodInvokeRequestedEvent = EventManager.RegisterRoutedEvent(
"MethodInvokeRequested", RoutingStrategy.Bubble, typeof(MethodInvokeRequestedRoutedEventHandler), typeof(MethodPresenter));
public event MethodInvokeRequestedRoutedEventHandler MethodInvokeRequested
{
add { AddHandler(MethodInvokeRequestedEvent, value); }
remove { RemoveHandler(MethodInvokeRequestedEvent, value); }
}
#endregion
#region MethodInvoked
public static readonly RoutedEvent MethodInvokedEvent = EventManager.RegisterRoutedEvent(
"MethodInvoked", RoutingStrategy.Bubble, typeof(MethodInvokedRoutedEventHandler), typeof(MethodPresenter));
public event MethodInvokedRoutedEventHandler MethodInvoked
{
add { AddHandler(MethodInvokedEvent, value); }
remove { RemoveHandler(MethodInvokedEvent, value); }
}
#endregion
#region MethodResultShown
public static readonly RoutedEvent MethodResultShownEvent = EventManager.RegisterRoutedEvent(
"MethodResultShown", RoutingStrategy.Bubble, typeof(MethodResultShownRoutedEventHandler), typeof(MethodPresenter));
public event MethodResultShownRoutedEventHandler MethodResultShown
{
add { AddHandler(MethodResultShownEvent, value); }
remove { RemoveHandler(MethodResultShownEvent, value); }
}
#endregion
#endregion
#region Commands
#region InvokeMethodCommand
private static RoutedCommand _invokeMethodCommand;
public static RoutedCommand InvokeMethodCommand
{
get { return _invokeMethodCommand ?? (_invokeMethodCommand = new RoutedCommand("InvokeMethod", typeof(MethodPresenter))); }
}
private static void CanExecuteInvokeMethodCommand(object sender, CanExecuteRoutedEventArgs e)
{
MethodPresenter mp = sender as MethodPresenter;
if (mp == null)
{
return;
}
e.CanExecute = mp.MethodInformation != null && mp.ObjectInstance != null;
}
private static void ExecuteInvokeMethodCommand(object sender, ExecutedRoutedEventArgs e)
{
MethodPresenter mp = sender as MethodPresenter;
if (mp == null)
{
return;
}
mp.InvokeMethod();
}
private void InvokeMethod()
{
MethodInfo mi = MethodInformation;
object obj = ObjectInstance;
if (mi == null || obj == null)
{
return;
}
IsInvoking = true;
object[] parameters = MethodParameters.Select(p => p.Value).ToArray();
// Raise MethodInvokeRequested event.
MethodInvokeRequestedRoutedEventArgs methodInvokeRequestedEventArgs =
new MethodInvokeRequestedRoutedEventArgs(MethodPresenter.MethodInvokeRequestedEvent)
{
MethodInformation = mi,
Parameters = parameters
};
RaiseEvent(methodInvokeRequestedEventArgs);
_invokeMethodThread = new Thread(() =>
{
OutputValueViewModel methodReturnValue = null;
OutputValueViewModel methodException = null;
bool isAborted = false;
try
{
object retVal = mi.Invoke(obj, parameters);
methodReturnValue = mi.ReturnType != typeof(void) ? new OutputValueViewModel(retVal) : null;
}
catch (ThreadAbortException tae)
{
isAborted = true;
}
catch (System.Reflection.TargetInvocationException tie)
{
methodException = new OutputValueViewModel(tie.InnerException);
}
catch (Exception ex)
{
methodException = new OutputValueViewModel(ex);
}
finally
{
if (!isAborted)
{
Dispatcher.BeginInvoke(DispatcherPriority.Normal,
new ThreadStart(() =>
{
if (methodReturnValue != null)
{
methodReturnValue.DataTemplates = DataTemplates;
}
if (methodException != null)
{
methodException.DataTemplates = DataTemplates;
}
MethodResultViewModel methodResult = new MethodResultViewModel
{
MethodName = mi.Name,
ResultTime = DateTime.Now,
MethodReturnValue = methodReturnValue,
MethodException = methodException
};
int paramInx = 0;
foreach (ParameterInfo pi in mi.GetParameters())
{
if (pi.IsOut || pi.ParameterType.IsByRef)
{
methodResult.MethodOutputs.Add(
new ParameterOutputValueViewModel(pi, parameters[paramInx])
{
DataTemplates = DataTemplates
});
}
paramInx++;
}
methodResult.Removed += OnMethodResultRemoved;
methodResult.Shown += OnMethodResultShown;
if (StoreMethodResults)
{
MethodResults.Add(methodResult);
HasResults = true;
}
CurrentMethodResult = methodResult;
IsInvoking = false;
// Raise MethodInvoked event.
MethodInvokedRoutedEventArgs methodInvokedEventArgs =
new MethodInvokedRoutedEventArgs(MethodPresenter.MethodInvokedEvent)
{
MethodInformation = mi,
MethodResult = methodResult
};
RaiseEvent(methodInvokedEventArgs);
}));
}
}
_invokeMethodThread = null;
});
_invokeMethodThread.Start();
}
private void OnMethodResultRemoved(MethodResultViewModel result)
{
if (CurrentMethodResult == result)
{
CurrentMethodResult = null;
}
MethodResults.Remove(result);
if (MethodResults.Count < 1)
{
HasResults = false;
}
}
private void OnMethodResultShown(MethodResultViewModel result)
{
// Raise MethodResultShown event.
MethodResultShownRoutedEventArgs newEventArgs = new MethodResultShownRoutedEventArgs(MethodPresenter.MethodResultShownEvent)
{
MethodResult = result
};
RaiseEvent(newEventArgs);
}
private Thread _invokeMethodThread;
#endregion
#region StopInvokeMethodCommand
private static RoutedCommand _stopInvokeMethodCommand;
public static RoutedCommand StopInvokeMethodCommand
{
get { return _stopInvokeMethodCommand ?? (_stopInvokeMethodCommand = new RoutedCommand("StopInvokeMethod", typeof(MethodPresenter))); }
}
private static void CanExecuteStopInvokeMethodCommand(object sender, CanExecuteRoutedEventArgs e)
{
MethodPresenter mp = sender as MethodPresenter;
if (mp == null)
{
return;
}
e.CanExecute = mp.IsInvoking;
}
private static void ExecuteStopInvokeMethodCommand(object sender, ExecutedRoutedEventArgs e)
{
MethodPresenter mp = sender as MethodPresenter;
if (mp == null)
{
return;
}
mp.StopInvokeMethod();
}
private void StopInvokeMethod()
{
if (_invokeMethodThread != null)
{
_invokeMethodThread.Abort();
_invokeMethodThread = null;
}
IsInvoking = false;
}
#endregion
#region ClearMethodResultsCommand
private static RoutedCommand _clearMethodResultsCommand;
public static RoutedCommand ClearMethodResultsCommand
{
get { return _clearMethodResultsCommand ?? (_clearMethodResultsCommand = new RoutedCommand("ClearMethodResults", typeof(MethodPresenter))); }
}
private static void CanExecuteClearMethodResultsCommand(object sender, CanExecuteRoutedEventArgs e)
{
MethodPresenter mp = sender as MethodPresenter;
if (mp == null)
{
return;
}
e.CanExecute = mp.HasResults;
}
private static void ExecuteClearMethodResultsCommand(object sender, ExecutedRoutedEventArgs e)
{
MethodPresenter mp = sender as MethodPresenter;
if (mp == null)
{
return;
}
mp.ClearMethodResults();
}
private void ClearMethodResults()
{
MethodResults.Clear();
HasResults = false;
}
#endregion
#endregion
static MethodPresenter()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(MethodPresenter), new FrameworkPropertyMetadata(typeof(MethodPresenter)));
CommandBinding invokeMethodBinding = new CommandBinding(InvokeMethodCommand,
ExecuteInvokeMethodCommand, CanExecuteInvokeMethodCommand);
CommandManager.RegisterClassCommandBinding(typeof(MethodPresenter), invokeMethodBinding);
CommandBinding stopInvokeMethodBinding = new CommandBinding(StopInvokeMethodCommand,
ExecuteStopInvokeMethodCommand, CanExecuteStopInvokeMethodCommand);
CommandManager.RegisterClassCommandBinding(typeof(MethodPresenter), stopInvokeMethodBinding);
CommandBinding clearMethodResultsBinding = new CommandBinding(ClearMethodResultsCommand,
ExecuteClearMethodResultsCommand, CanExecuteClearMethodResultsCommand);
CommandManager.RegisterClassCommandBinding(typeof(MethodPresenter), clearMethodResultsBinding);
}
}
}