public void TestGetterAndSetter() { var model = new Model(); { var property = typeof(Model).GetProperty("IntValue"); var getter = DelegateUtility.CreateGetter(property); var setter = DelegateUtility.CreateSetter(property); // call setter setter(model, 11); Assert.AreEqual(11, model.IntValue); // call getter int value = (int)getter(model); Assert.AreEqual(11, value); } { var property = typeof(Model).GetProperty("StringValue"); var getter = DelegateUtility.CreateGetter(property); var setter = DelegateUtility.CreateSetter(property); // call setter setter(model, "Test"); Assert.AreEqual("Test", model.StringValue); // call getter string value = (string)getter(model); Assert.AreEqual("Test", value); } }
private bool ExecuteTasksFinally(IEnumerable <TaskDefinition> taskInfos, out List <TaskDefinition> failureTasks) { List <bool> result = new List <bool>(); failureTasks = new List <TaskDefinition>(); TaskDefinition toExecute; while ((toExecute = this.queue.Dequeue()) != null) { bool ret = DelegateUtility.ContinuousInvoke <TaskDefinition>(this.ExecuteTask, toExecute, toExecute.RetryTimes); // 运行触发器逻辑 if (!this.ExecuteTrigger(toExecute)) { // 触发器执行失败直接退出 return(false); } result.Add(ret); if (!ret) { failureTasks.Add(toExecute); if (!toExecute.HasFlag((int)TaskFlags.IgnoreFailure)) { return(false); } } } return(result.All(r => r)); }
private static Stream CreateXmlCore <TTuple>(ActionFactory <TTuple> factory, Action <XmlWriterSettings> setup) where TTuple : Template <XmlWriter> { var options = DelegateUtility.ConfigureAction(setup, OverrideDefaultSettings); Stream output; MemoryStream tempOutput = null; try { tempOutput = new MemoryStream(); using (XmlWriter writer = XmlWriter.Create(tempOutput, options)) { factory.GenericArguments.Arg1 = writer; factory.ExecuteMethod(); writer.Flush(); } tempOutput.Flush(); tempOutput.Position = 0; output = tempOutput; tempOutput = null; } catch (Exception ex) { List <object> parameters = new List <object>(); parameters.AddRange(factory.GenericArguments.ToArray()); parameters.Add(options); throw ExceptionUtility.Refine(new InvalidOperationException("There is an error in the XML document.", ex), factory.DelegateInfo, parameters.ToArray()).Unwrap(); } finally { tempOutput?.Dispose(); } return(output); }
public void SimpleCastTest() { Calc calc = Add; Calculate calculate = DelegateUtility.Cast <Calculate>(calc); Assert.That(calculate(2), Is.EqualTo(3)); }
public void NullCastTest() { Calc calc = null; Calculate calculate = DelegateUtility.Cast <Calculate>(calc); Assert.That(calculate, Is.Null); }
void CreateInstance() { //LayerProperties[] available_layers = DelegateUtility.EnumerateToArray<LayerProperties> ( vk.EnumerateInstanceLayerProperties ); ExtensionProperties[] available_extensions = DelegateUtility.EnumerateToArray <ExtensionProperties> (vk.EnumerateInstanceExtensionProperties, IntPtr.Zero); List <string> extensions = new List <string> { KhrWin32Surface.EXTENSION_NAME, KhrSurface.EXTENSION_NAME }; for (int i = 0; i < extensions.Count; ++i) { if (!CheckExtensionAvailability(extensions[i], available_extensions)) { //std::cout << "Could not find instance extension named \"" << extensions[i] << "\"!" << std::endl; return; } } if (CheckExtensionAvailability(ExtDebugReport.EXTENSION_NAME, available_extensions)) { extensions.Add(ExtDebugReport.EXTENSION_NAME); supportDebugReport = true; } var exPtr = MarshalUtility.AllocateString(extensions); ApplicationInfo application_info = new ApplicationInfo { sType = StructureType.ApplicationInfo, pNext = IntPtr.Zero, pApplicationName = (byte *)Marshal.StringToHGlobalAnsi("Vulkan Window"), applicationVersion = new Version(1, 0, 0), pEngineName = (byte *)Marshal.StringToHGlobalAnsi("Vulkan Tutorial"), engineVersion = new Version(1, 0, 0), apiVersion = new Version(1, 0, 0), }; InstanceCreateInfo instance_create_info = new InstanceCreateInfo { sType = StructureType.InstanceCreateInfo, pNext = IntPtr.Zero, flags = 0, pApplicationInfo = &application_info, enabledLayerCount = 0, ppEnabledLayerNames = (byte *)0, enabledExtensionCount = (uint)extensions.Count, ppEnabledExtensionNames = (byte *)exPtr, }; vk.CreateInstance(ref instance_create_info, (AllocationCallbacks *)0, out vulkan.Instance).CheckError(); MarshalUtility.FreeString(exPtr, extensions.Count); Marshal.FreeHGlobal((IntPtr)application_info.pApplicationName); Marshal.FreeHGlobal((IntPtr)application_info.pEngineName); }
public void MulticastCastTest() { Calc calc = Add; calc += Subtract; Calculate calculate = DelegateUtility.Cast <Calculate>(calc); Assert.That(calculate(2), Is.EqualTo(1)); }
static void SceneViewOverlay_Window(GUIContent title, Action <Object, SceneView> sceneViewFunc, int order, Object target) { k_SceneViewOverlay_Window.Invoke(null, new[] { title, DelegateUtility.Cast(sceneViewFunc, k_SceneViewOverlay_WindowFunction), order, target, Enum.ToObject(k_SceneViewOverlay_WindowDisplayOption, 1) }); }
/// <summary> /// Converts the specified <paramref name="value"/> to a <see cref="Stream"/>. /// </summary> /// <param name="value">The string to be converted.</param> /// <param name="setup">The <see cref="EncodingOptions"/> which need to be configured.</param> /// <returns>A <b><see cref="System.IO.Stream"/></b> object.</returns> /// <remarks><see cref="EncodingOptions"/> will be initialized with <see cref="EncodingOptions.DefaultPreambleSequence"/> and <see cref="EncodingOptions.DefaultEncoding"/>.</remarks> public static Stream FromString(string value, Action <EncodingOptions> setup = null) { Validator.ThrowIfNull(value, nameof(value)); MemoryStream output = DelegateUtility.SafeInvokeDisposable(() => { var m = new MemoryStream(ByteConverter.FromString(value, setup)); m.Position = 0; return(m); }); return(output); }
/// <summary> /// Copies the specified <paramref name="reader"/> using the specified delegate <paramref name="copier"/> and returns the result as an XML stream. /// </summary> /// <typeparam name="T">The type of the parameter of the delegate <paramref name="copier"/>.</typeparam> /// <param name="reader">The <see cref="XmlReader"/> object that contains the XML data.</param> /// <param name="copier">The delegate that will create an in-memory copy of <paramref name="reader"/> as a XML stream.</param> /// <param name="arg">The parameter of the delegate <paramref name="copier"/>.</param> /// <param name="setup">The <see cref="XmlCopyOptions"/> which need to be configured.</param> /// <returns>A <see cref="Stream"/> holding the XML copied by the delegate <paramref name="copier"/> from the source <paramref name="reader"/>.</returns> /// <exception cref="System.ArgumentNullException"> /// <paramref name="reader"/> is null - or - <paramref name="copier"/> is null. /// </exception> /// <remarks>This method uses a default implementation of <see cref="XmlWriterSettings"/> as specified by <see cref="CreateSettings"/>.</remarks> public static Stream Copy <T>(XmlReader reader, Action <XmlWriter, XmlReader, T> copier, T arg, Action <XmlCopyOptions> setup = null) { Validator.ThrowIfNull(reader, nameof(reader)); Validator.ThrowIfNull(copier, nameof(copier)); var options = DelegateUtility.ConfigureAction(setup); try { return(CreateXml(copier, reader, arg, options.WriterSettings)); } finally { if (!options.LeaveStreamOpen) { reader.Dispose(); } } }
/// <summary> /// 执行指定的触发器 /// </summary> /// <param name="trigger">要执行的触发器</param> /// <returns>返回触发器执行是否成功</returns> private bool ExecuteTriggerFinal(TaskTrigger trigger) { foreach (TaskDefinition task in trigger.TaskList) { // 触发器触发的Task也执行重试逻辑 bool ret = DelegateUtility.ContinuousInvoke <TaskDefinition>(this.ExecuteTask, task, task.RetryTimes); if (!ret) { // 执行失败, return(false); } else { // 执行成功,继续执行下一个 } } return(true); }
private bool ExecutePostTasks(IEnumerable <TaskDefinition> postTasks, out List <TaskDefinition> failureTasks) { List <bool> result = new List <bool>(); failureTasks = new List <TaskDefinition>(); foreach (TaskDefinition task in postTasks) { bool ret = DelegateUtility.ContinuousInvoke <TaskDefinition>(this.ExecuteTask, task, task.RetryTimes); // 运行触发器逻辑 this.ExecuteTrigger(task); result.Add(ret); if (!ret) { failureTasks.Add(task); } } return(result.All(r => r)); }
public void TestImplicitOperatorWithNullValue() { { var method = GetImplicitConverter(typeof(Vector2), typeof(Vector2), typeof(Vector3)); var function = DelegateUtility.CreateImplicitOperator(method); Assert.IsNotNull(function); // will return default value Vector3 value = (Vector3)method.Invoke(null, new object[] { null }); Assert.AreEqual(Vector3.zero, value); try { // call delegate will failed function.Invoke(null); } catch (Exception ex) { Assert.IsTrue(ex is NullReferenceException); } } { var method = GetImplicitConverter(typeof(Vector2), typeof(Vector3), typeof(Vector2)); var function = DelegateUtility.CreateImplicitOperator(method); Assert.IsNotNull(function); // will return default value Vector2 value = (Vector2)method.Invoke(null, new object[] { null }); Assert.AreEqual(Vector2.zero, value); try { // call delegate will failed function.Invoke(null); } catch (Exception ex) { Assert.IsTrue(ex is NullReferenceException); } } }
public void TestImplicitOperator() { { var method = GetImplicitConverter(typeof(Vector2), typeof(Vector2), typeof(Vector3)); var function = DelegateUtility.CreateImplicitOperator(method); Assert.IsNotNull(function); Vector3 v3 = (Vector3)function.Invoke(Vector2.one); Assert.AreEqual(new Vector3(1f, 1f, 0f), v3); } { var method = GetImplicitConverter(typeof(Vector2), typeof(Vector3), typeof(Vector2)); var function = DelegateUtility.CreateImplicitOperator(method); Assert.IsNotNull(function); Vector2 v2 = (Vector2)function.Invoke(Vector3.one); Assert.AreEqual(new Vector2(1f, 1f), v2); } }
internal static Delegate CastValidator(ObjectFieldValidator validator) { return(DelegateUtility.Cast(validator, k_ObjectFieldValidator)); }
private bool CheckDataBinFunIsExist(Action <T> fun) { return(DelegateUtility.CheckFunIsExist(bindEvent, fun)); }
bool CheckPhysicalDeviceProperties(PhysicalDevice physical_device, out uint graphics_queue_family_index, out uint present_queue_family_index) { graphics_queue_family_index = uint.MaxValue; present_queue_family_index = uint.MaxValue; ExtensionProperties[] available_extensions = DelegateUtility.EnumerateToArray <ExtensionProperties> ( vk.EnumerateDeviceExtensionProperties, (IntPtr)physical_device, IntPtr.Zero); if (available_extensions == null) { //std::cout << "Error occurred during physical device " << physical_device << " extensions enumeration!" << std::endl; return(false); } string[] device_extensions = { KhrSwapchain.EXTENSION_NAME }; for (int i = 0; i < device_extensions.Length; ++i) { if (!CheckExtensionAvailability(device_extensions[i], available_extensions)) { //std::cout << "Physical device " << physical_device << " doesn't support extension named \"" << device_extensions[i] << "\"!" << std::endl; return(false); } } PhysicalDeviceProperties device_properties; PhysicalDeviceFeatures device_features; vk.GetPhysicalDeviceProperties(physical_device, out device_properties); vk.GetPhysicalDeviceFeatures(physical_device, out device_features); if (device_properties.apiVersion.Major < 1 || device_properties.limits.maxImageDimension2D < 4096) { //std::cout << "Physical device " << physical_device << " doesn't support required parameters!" << std::endl; return(false); } QueueFamilyProperties[] queue_family_properties = DelegateUtility.EnumerateToArray <QueueFamilyProperties> ( vk.GetPhysicalDeviceQueueFamilyProperties, (IntPtr)physical_device); if (queue_family_properties == null) { //std::cout << "Physical device " << physical_device << " doesn't have any queue families!" << std::endl; return(false); } bool[] queue_present_support = new bool[queue_family_properties.Length]; for (uint i = 0; i < queue_family_properties.Length; ++i) { Boolean32 support; khrSurface.GetPhysicalDeviceSurfaceSupportKHR(physical_device, i, vulkan.PresentationSurface, out support).CheckError(); queue_present_support[i] = support; if ((queue_family_properties[i].queueCount > 0) && (queue_family_properties[i].queueFlags & QueueFlagBits.GraphicsBit) > 0) { // Select first queue that supports graphics if (graphics_queue_family_index == uint.MaxValue) { graphics_queue_family_index = i; } // If there is queue that supports both graphics and present - prefer it if (support) { graphics_queue_family_index = i; present_queue_family_index = i; return(true); } } } if (present_queue_family_index == uint.MaxValue) { present_queue_family_index = (uint)Array.IndexOf(queue_present_support, true); } if (present_queue_family_index == uint.MaxValue || graphics_queue_family_index == uint.MaxValue) { //std::cout << "Could not find queue families with required properties on physical device " << physical_device << "!" << std::endl; return(false); } return(true); }
void CreateDevice() { PhysicalDevice[] physical_devices = DelegateUtility.EnumerateToArray <PhysicalDevice> (vk.EnumeratePhysicalDevices, (IntPtr)vulkan.Instance); if (physical_devices == null) { //std::cout << "Error occurred during physical devices enumeration!" << std::endl; return; } uint selected_graphics_queue_family_index = uint.MaxValue; uint selected_present_queue_family_index = uint.MaxValue; for (int i = 0; i < physical_devices.Length; ++i) { if (CheckPhysicalDeviceProperties(physical_devices[i], out selected_graphics_queue_family_index, out selected_present_queue_family_index)) { vulkan.PhysicalDevice = physical_devices[i]; } } if (vulkan.PhysicalDevice.IsZero || selected_graphics_queue_family_index == uint.MaxValue || selected_present_queue_family_index == uint.MaxValue) { //std::cout << "Could not select physical device based on the chosen properties!" << std::endl; return; } var queue_create_infos = stackalloc DeviceQueueCreateInfo[2]; uint count = 1; float *queue_priorities = stackalloc float[1]; queue_priorities[0] = 1.0f; queue_create_infos[0] = new DeviceQueueCreateInfo { sType = StructureType.DeviceQueueCreateInfo, // VkStructureType sType pNext = IntPtr.Zero, // const void *pNext flags = 0, // VkDeviceQueueCreateFlagBits flags queueFamilyIndex = selected_graphics_queue_family_index, // uint32_t queueFamilyIndex queueCount = 1, // uint32_t queueCount pQueuePriorities = queue_priorities // const float *pQueuePriorities }; if (selected_graphics_queue_family_index != selected_present_queue_family_index) { queue_create_infos[1] = new DeviceQueueCreateInfo { sType = StructureType.DeviceQueueCreateInfo, // VkStructureType sType pNext = IntPtr.Zero, // const void *pNext flags = 0, // VkDeviceQueueCreateFlagBits flags queueFamilyIndex = selected_present_queue_family_index, // uint32_t queueFamilyIndex queueCount = 1, // uint32_t queueCount pQueuePriorities = queue_priorities // const float *pQueuePriorities }; count++; } const uint exCount = 1; var exPtr = MarshalUtility.AllocateString(new string[] { KhrSwapchain.EXTENSION_NAME }); DeviceCreateInfo device_create_info = new DeviceCreateInfo { sType = StructureType.DeviceCreateInfo, // VkStructureType sType pNext = IntPtr.Zero, // const void *pNext flags = 0, // VkDeviceCreateFlagBits flags queueCreateInfoCount = count, // uint32_t queueCreateInfoCount pQueueCreateInfos = queue_create_infos, // const VkDeviceQueueCreateInfo *pQueueCreateInfos enabledLayerCount = 0, // uint32_t enabledLayerCount ppEnabledLayerNames = (byte *)0, // const char * const *ppEnabledLayerNames enabledExtensionCount = exCount, // uint32_t enabledExtensionCount ppEnabledExtensionNames = (byte *)exPtr, // const char * const *ppEnabledExtensionNames pEnabledFeatures = (PhysicalDeviceFeatures *)0 // const VkPhysicalDeviceFeatures *pEnabledFeatures }; vk.CreateDevice(vulkan.PhysicalDevice, ref device_create_info, (AllocationCallbacks *)0, out vulkan.Device).CheckError(); MarshalUtility.FreeString(exPtr, (int)exCount); }
public static void RegisterImplicitOperator <T1, T2>() { DelegateUtility.CreateImplicitOperatorImpl <T1, T2>(null); }
void CreateSwapChain() { CanRender = false; if (!vulkan.Device.IsZero) { vk.DeviceWaitIdle(vulkan.Device); } if (vulkan.SwapChain.Images != null) { for (int i = 0; i < vulkan.SwapChain.Images.Length; ++i) { if (vulkan.SwapChain.Images[i].View != ImageView.Zero) { vk.DestroyImageView(vulkan.Device, vulkan.SwapChain.Images[i].View); } } } SurfaceCapabilitiesKHR surface_capabilities; khrSurface.GetPhysicalDeviceSurfaceCapabilitiesKHR(vulkan.PhysicalDevice, vulkan.PresentationSurface, out surface_capabilities).CheckError(); var surface_formats = DelegateUtility.EnumerateToArray <SurfaceFormatKHR> (khrSurface.GetPhysicalDeviceSurfaceFormatsKHR, (IntPtr)vulkan.PhysicalDevice, (ulong)vulkan.PresentationSurface); var present_modes = DelegateUtility.EnumerateToArray <int> (khrSurface.GetPhysicalDeviceSurfacePresentModesKHR, (IntPtr)vulkan.PhysicalDevice, (ulong)vulkan.PresentationSurface); uint desired_number_of_images = GetSwapChainNumImages(ref surface_capabilities); SurfaceFormatKHR desired_format = GetSwapChainFormat(surface_formats); Extent2D desired_extent = GetSwapChainExtent(ref surface_capabilities); ImageUsageFlagBits desired_usage = GetSwapChainUsageFlagBits(ref surface_capabilities); SurfaceTransformFlagBitsKHR desired_transform = GetSwapChainTransform(ref surface_capabilities); PresentModeKHR desired_present_mode = GetSwapChainPresentMode(present_modes); SwapchainKHR old_swap_chain = vulkan.SwapChain.Handle; if (desired_usage == (ImageUsageFlagBits)(-1)) { return; } if (desired_present_mode == (PresentModeKHR)(-1)) { return; } if ((desired_extent.width == 0) || (desired_extent.height == 0)) { // Current surface size is (0, 0) so we can't create a swap chain and render anything (CanRender == false) // But we don't wont to kill the application as this situation may occur i.e. when window gets minimized return; } SwapchainCreateInfoKHR swap_chain_create_info = new SwapchainCreateInfoKHR { sType = StructureType.SwapchainCreateInfoKhr, // VkStructureType sType pNext = IntPtr.Zero, // const void *pNext flags = 0, // VkSwapchainCreateFlagBitsKHR flags surface = vulkan.PresentationSurface, // VkSurfaceKHR surface minImageCount = desired_number_of_images, // uint32_t minImageCount imageFormat = desired_format.format, // VkFormat imageFormat imageColorSpace = desired_format.colorSpace, // VkColorSpaceKHR imageColorSpace imageExtent = desired_extent, // VkExtent2D imageExtent imageArrayLayers = 1, // uint32_t imageArrayLayers imageUsage = desired_usage, // VkImageUsageFlagBits imageUsage imageSharingMode = SharingMode.Exclusive, // VkSharingMode imageSharingMode queueFamilyIndexCount = 0, // uint32_t queueFamilyIndexCount pQueueFamilyIndices = (uint *)0, // const uint32_t *pQueueFamilyIndices preTransform = desired_transform, // VkSurfaceTransformFlagBitsKHR preTransform compositeAlpha = CompositeAlphaFlagBitsKHR.OpaqueBitKhr, // VkCompositeAlphaFlagBitsKHR compositeAlpha presentMode = desired_present_mode, // VkPresentModeKHR presentMode clipped = Boolean32.True, // VkBool32 clipped oldSwapchain = old_swap_chain // VkSwapchainKHR oldSwapchain }; khrSwapChain.CreateSwapchainKHR(vulkan.Device, ref swap_chain_create_info, (AllocationCallbacks *)0, out vulkan.SwapChain.Handle).CheckError(); if (!old_swap_chain.IsZero) { khrSwapChain.DestroySwapchainKHR(vulkan.Device, old_swap_chain); } vulkan.SwapChain.Format = desired_format.format; var images = DelegateUtility.EnumerateToArray <Image> (khrSwapChain.GetSwapchainImagesKHR, (IntPtr)vulkan.Device, (ulong)vulkan.SwapChain.Handle); if (vulkan.SwapChain.Images == null || vulkan.SwapChain.Images.Length != images.Length) { vulkan.SwapChain.Images = new ImageParameters[images.Length]; } for (int i = 0; i < images.Length; ++i) { vulkan.SwapChain.Images[i].Handle = images[i]; } vulkan.SwapChain.Extent = desired_extent; CreateSwapChainImageViews(); }
public static void RegisterProperty <TObject, TValue>() { DelegateUtility.CreateGetterImpl <TObject, TValue>(null); DelegateUtility.CreateSetterImpl <TObject, TValue>(null); }
void Bind( BindingExpression bindingExpression, object dataContext, string[] sourcePath, IValueConverter converter, PropertyInfo targetProperty, IList <Action> localRemoveActions, IList <Action> globalRemoveActions, int position) { object currentContext = dataContext; var pathSplitLength = sourcePath.Length; int lastIndex = pathSplitLength - 1; PropertyBinding[] propertyBinding = new PropertyBinding[1]; for (int i = position; i < pathSplitLength; i++) { if (currentContext == null) { break; } var inpc = currentContext as INotifyPropertyChanged; string sourceSegment = sourcePath[i]; var sourceProperty = currentContext.GetType().GetProperty(sourceSegment); if (i == lastIndex) /* The value. */ { /* Add a property binding between the source (the viewmodel) * and the target (the view) so we can update the target property * when the source property changes (a OneWay binding). */ propertyBinding[0] = new PropertyBinding { SourceProperty = sourceProperty, TargetProperty = targetProperty, Converter = converter, ConverterParameter = bindingExpression.ConverterParameter, View = bindingExpression.View }; { /* When this value changes, the value must be pushed to the target. */ if (inpc != null && bindingExpression.Mode != BindingMode.OneTime) { object context = currentContext; PropertyChangedEventHandler handler = delegate(object sender, PropertyChangedEventArgs args) { if (args.PropertyName != sourceSegment) { return; } PropertyBinding binding = propertyBinding[0]; if (binding != null) { if (binding.PreventUpdateForTargetProperty) { return; } try { binding.PreventUpdateForSourceProperty = true; SetTargetProperty(sourceProperty, context, binding.View, binding.TargetProperty, binding.Converter, binding.ConverterParameter); } finally { binding.PreventUpdateForSourceProperty = false; } } }; inpc.PropertyChanged += handler; Action removeHandler = () => { inpc.PropertyChanged -= handler; propertyBinding[0] = null; }; localRemoveActions.Add(removeHandler); globalRemoveActions.Add(removeHandler); } } /* Determine if the target is an event, * in which case use that to trigger an update. */ var bindingEvent = bindingExpression.View.GetType().GetEvent(bindingExpression.Target); if (bindingEvent != null) { /* The target is an event of the view. */ if (sourceProperty != null) { /* The source must be an ICommand so we can call its Execute method. */ var command = sourceProperty.GetValue(currentContext) as ICommand; if (command == null) { throw new InvalidOperationException( $"The source property {bindingExpression.Source}, " + $"bound to the event {bindingEvent.Name}, " + "needs to implement the interface ICommand."); } /* Subscribe to the specified event to execute * the command when the event is raised. */ var executeMethodInfo = typeof(ICommand).GetMethod(nameof(ICommand.Execute), new[] { typeof(object) }); Action action = () => { executeMethodInfo.Invoke(command, new object[] { null }); }; Action removeAction = DelegateUtility.AddHandler(bindingExpression.View, bindingExpression.Target, action); localRemoveActions.Add(removeAction); globalRemoveActions.Add(removeAction); /* Subscribe to the CanExecuteChanged event of the command * to disable or enable the view associated to the command. */ var view = bindingExpression.View; var enabledProperty = view.GetType().GetProperty(viewEnabledPropertyName); if (enabledProperty != null) { enabledProperty.SetValue(view, command.CanExecute(null)); Action canExecuteChangedAction = () => enabledProperty.SetValue(view, command.CanExecute(null)); removeAction = DelegateUtility.AddHandler( command, nameof(ICommand.CanExecuteChanged), canExecuteChangedAction); localRemoveActions.Add(removeAction); globalRemoveActions.Add(removeAction); } } else /* sourceProperty == null */ { /* If the Source property of the data context * is not a property, check if it's a method. */ var sourceMethod = currentContext.GetType().GetMethod(sourceSegment, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static); if (sourceMethod == null) { throw new InvalidOperationException( $"No property or event named {bindingExpression.Source} " + $"found to bind it to the event {bindingEvent.Name}."); } var parameterCount = sourceMethod.GetParameters().Length; if (parameterCount > 1) { /* Only calls to methods without parameters are supported. */ throw new InvalidOperationException( $"Method {sourceMethod.Name} should not have zero or one parameter " + $"to be called when event {bindingEvent.Name} is raised."); } /* It's a method therefore subscribe to the specified event * to execute the method when event is raised. */ var context = currentContext; Action removeAction = DelegateUtility.AddHandler( bindingExpression.View, bindingExpression.Target, () => { sourceMethod.Invoke(context, parameterCount > 0 ? new[] { context } : null); }); localRemoveActions.Add(removeAction); globalRemoveActions.Add(removeAction); } } else /* bindingEvent == null */ { if (sourceProperty == null) { throw new InvalidOperationException( $"Source property {bindingExpression.Source} does not exist " + $"on {currentContext?.GetType().Name ?? "null"}."); } /* Set initial binding value. */ SetTargetProperty(sourceProperty, currentContext, bindingExpression.View, targetProperty, converter, bindingExpression.ConverterParameter); if (bindingExpression.Mode == BindingMode.TwoWay) { /* TwoWay bindings require that the ViewModel property be updated * when an event is raised on the bound view. */ string changedEvent = bindingExpression.ViewValueChangedEvent; if (!string.IsNullOrWhiteSpace(changedEvent)) { var context = currentContext; Action changeAction = () => { var pb = propertyBinding[0]; if (pb == null) { return; } ViewValueChangedHandler.HandleViewValueChanged(pb, context); }; var view = bindingExpression.View; var removeHandler = DelegateUtility.AddHandler(view, changedEvent, changeAction); localRemoveActions.Add(removeHandler); globalRemoveActions.Add(removeHandler); } else { var binding = propertyBinding[0]; IViewBinder binder; if (ViewBinderRegistry.TryGetViewBinder( binding.View.GetType(), binding.TargetProperty.Name, out binder)) { var unbindAction = binder.BindView(binding, currentContext); if (unbindAction != null) { localRemoveActions.Add(unbindAction); globalRemoveActions.Add(unbindAction); } } else { if (Debugger.IsAttached) { Debugger.Break(); } } } } } } else { /* The source is a child of another object, * therefore we must subscribe to the parents PropertyChanged event * and re-bind when the child changes. */ if (inpc != null && bindingExpression.Mode != BindingMode.OneTime) { var context = currentContext; var iCopy = i; PropertyChangedEventHandler handler = delegate(object sender, PropertyChangedEventArgs args) { if (args.PropertyName != sourceSegment) { return; } /* Remove existing child event subscribers. */ var removeActionCount = localRemoveActions.Count; for (int j = position; j < removeActionCount; j++) { var removeAction = localRemoveActions[j]; try { removeAction(); } catch (Exception ex) { /* TODO: log error. */ } localRemoveActions.Remove(removeAction); globalRemoveActions.Remove(removeAction); } propertyBinding[0] = null; /* Bind child bindings. */ Bind(bindingExpression, context, sourcePath, converter, targetProperty, localRemoveActions, globalRemoveActions, iCopy); }; inpc.PropertyChanged += handler; Action removeHandler = () => { inpc.PropertyChanged -= handler; propertyBinding[0] = null; }; localRemoveActions.Add(removeHandler); globalRemoveActions.Add(removeHandler); } currentContext = sourceProperty?.GetValue(currentContext); } } }
public void UnhookUpdate(ActionDelegate action) { EditorApplication.update -= DelegateUtility.Cast <EditorApplication.CallbackFunction>(action); }