NullPointerException
s - исключения, возникающие при попытке использовать ссылку, которая указывает на отсутствие местоположения в памяти (null), как если бы она ссылалась на объект. Вызов метода по нулевой ссылке или попытка получить доступ к полю нулевой ссылки вызовет функцию NullPointerException
. Они наиболее распространены, но другие способы перечислены на странице NullPointerException
javadoc.
Вероятно, самый быстрый пример кода, который я мог бы придумать для иллюстрации NullPointerException
, be:
public class Example {
public static void main(String[] args) {
Object obj = null;
obj.hashCode();
}
}
В первой строке внутри main
я явно устанавливаю ссылку Object
obj
равной null
. Это означает, что у меня есть ссылка, но она не указывает на какой-либо объект. После этого я пытаюсь обработать ссылку так, как если бы она указывала на объект, вызывая метод на нем. Это приводит к NullPointerException
, потому что нет кода для выполнения в местоположении, на которое указывает ссылка.
(Это техничность, но я думаю, что она упоминает: ссылка, которая указывает на null, равна 't то же, что и указатель C, указывающий на недопустимую ячейку памяти. Нулевой указатель буквально не указывает на в любом месте , который отличается от указаний на местоположение, которое оказывается недопустимым.)
Я нашел решение на форумы MSDN . Пример кода ниже удалит весь Click
события от button1
.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
button1.Click += button1_Click;
button1.Click += button1_Click2;
button2.Click += button2_Click;
}
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("Hello");
}
private void button1_Click2(object sender, EventArgs e)
{
MessageBox.Show("World");
}
private void button2_Click(object sender, EventArgs e)
{
RemoveClickEvent(button1);
}
private void RemoveClickEvent(Button b)
{
FieldInfo f1 = typeof(Control).GetField("EventClick",
BindingFlags.Static | BindingFlags.NonPublic);
object obj = f1.GetValue(b);
PropertyInfo pi = b.GetType().GetProperty("Events",
BindingFlags.NonPublic | BindingFlags.Instance);
EventHandlerList list = (EventHandlerList)pi.GetValue(b, null);
list.RemoveHandler(obj, list[obj]);
}
}
}
От Удаление Всех Обработчиков событий :
Непосредственно не, в значительной степени потому что Вы не можете просто установить событие в NULL.
Косвенно, Вы могли сделать фактическое событие частным и создать свойство вокруг этого, которое отслеживает всех делегатов, являющихся, добавил/вычел к нему.
Берут следующее:
List<EventHandler> delegates = new List<EventHandler>(); private event EventHandler MyRealEvent; public event EventHandler MyEvent { add { MyRealEvent += value; delegates.Add(value); } remove { MyRealEvent -= value; delegates.Remove(value); } } public void RemoveAllEvents() { foreach(EventHandler eh in delegates) { MyRealEvent -= eh; } delegates.Clear(); }
Если Вы reaallly должен сделать это..., он возьмет отражение и некоторое время, чтобы сделать это. Обработчиками событий управляют в event-to-delegate-map в управлении. Вам было бы нужно к
Короче говоря, большая работа. Это возможно в теории... Я никогда не пробовал что-то вроде этого.
Видят, можно ли иметь лучший контроль над подписыванием - отказываются от подписки фаза для управления.
Я нашел другое рабочее решение Douglas.
Этот метод удаляет все обработчики событий, которые установлены на определенном routet событии на элементе.
Использование это как
Remove_RoutedEventHandlers(myImage, Image.MouseLeftButtonDownEvent);
Полный код:
/// <summary>
/// Removes all event handlers subscribed to the specified routed event from the specified element.
/// </summary>
/// <param name="element">The UI element on which the routed event is defined.</param>
/// <param name="RoutetEvent_ToRemove">The routed event for which to remove the event handlers.</param>
public static void RemoveRoutedEventHandlers(UIElement UIElement_Target, RoutedEvent RoutetEvent_ToRemove)
{
// Get the EventHandlersStore instance which holds event handlers for the specified element.
// The EventHandlersStore class is declared as internal.
PropertyInfo PropertyInfo_EventHandlersStore = typeof(UIElement).GetProperty(
"EventHandlersStore", BindingFlags.Instance | BindingFlags.NonPublic);
object oEventHandlersStore = PropertyInfo_EventHandlersStore.GetValue(UIElement_Target, null);
// If there's no event handler subscribed, return
if (oEventHandlersStore == null) return;
// Invoke the GetRoutedEventHandlers method on the EventHandlersStore instance
// for getting an array of the subscribed event handlers.
MethodInfo MethodInfo_RoutedEventHandlers = oEventHandlersStore.GetType().GetMethod(
"GetRoutedEventHandlers", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
RoutedEventHandlerInfo[] RoutedEventHandlerInfos = (RoutedEventHandlerInfo[])MethodInfo_RoutedEventHandlers.Invoke(
oEventHandlersStore, new object[] { RoutetEvent_ToRemove });
// Iteratively remove all routed event handlers from the element.
foreach (RoutedEventHandlerInfo RoutedEventHandlerInfo_Tmp in RoutedEventHandlerInfos)
UIElement_Target.RemoveHandler(RoutetEvent_ToRemove, RoutedEventHandlerInfo_Tmp.Handler);
}
Удаление несуществующего обработчика событий не причинит никакого вреда. Поэтому, если вы знаете, какие могут быть обработчики, вы можете просто удалить их все. У меня как раз был похожий случай. В некоторых случаях это может помочь.
Например:
// Add handlers...
if (something)
{
c.Click += DoesSomething;
}
else
{
c.Click += DoesSomethingElse;
}
// Remove handlers...
c.Click -= DoesSomething;
c.Click -= DoesSomethingElse;
Я только что нашел Как приостановить события при установке свойства элемента управления WinForms . Он удалит все события из элемента управления:
namespace CMessWin05
{
public class EventSuppressor
{
Control _source;
EventHandlerList _sourceEventHandlerList;
FieldInfo _headFI;
Dictionary<object, Delegate[]> _handlers;
PropertyInfo _sourceEventsInfo;
Type _eventHandlerListType;
Type _sourceType;
public EventSuppressor(Control control)
{
if (control == null)
throw new ArgumentNullException("control", "An instance of a control must be provided.");
_source = control;
_sourceType = _source.GetType();
_sourceEventsInfo = _sourceType.GetProperty("Events", BindingFlags.Instance | BindingFlags.NonPublic);
_sourceEventHandlerList = (EventHandlerList)_sourceEventsInfo.GetValue(_source, null);
_eventHandlerListType = _sourceEventHandlerList.GetType();
_headFI = _eventHandlerListType.GetField("head", BindingFlags.Instance | BindingFlags.NonPublic);
}
private void BuildList()
{
_handlers = new Dictionary<object, Delegate[]>();
object head = _headFI.GetValue(_sourceEventHandlerList);
if (head != null)
{
Type listEntryType = head.GetType();
FieldInfo delegateFI = listEntryType.GetField("handler", BindingFlags.Instance | BindingFlags.NonPublic);
FieldInfo keyFI = listEntryType.GetField("key", BindingFlags.Instance | BindingFlags.NonPublic);
FieldInfo nextFI = listEntryType.GetField("next", BindingFlags.Instance | BindingFlags.NonPublic);
BuildListWalk(head, delegateFI, keyFI, nextFI);
}
}
private void BuildListWalk(object entry, FieldInfo delegateFI, FieldInfo keyFI, FieldInfo nextFI)
{
if (entry != null)
{
Delegate dele = (Delegate)delegateFI.GetValue(entry);
object key = keyFI.GetValue(entry);
object next = nextFI.GetValue(entry);
Delegate[] listeners = dele.GetInvocationList();
if(listeners != null && listeners.Length > 0)
_handlers.Add(key, listeners);
if (next != null)
{
BuildListWalk(next, delegateFI, keyFI, nextFI);
}
}
}
public void Resume()
{
if (_handlers == null)
throw new ApplicationException("Events have not been suppressed.");
foreach (KeyValuePair<object, Delegate[]> pair in _handlers)
{
for (int x = 0; x < pair.Value.Length; x++)
_sourceEventHandlerList.AddHandler(pair.Key, pair.Value[x]);
}
_handlers = null;
}
public void Suppress()
{
if (_handlers != null)
throw new ApplicationException("Events are already being suppressed.");
BuildList();
foreach (KeyValuePair<object, Delegate[]> pair in _handlers)
{
for (int x = pair.Value.Length - 1; x >= 0; x--)
_sourceEventHandlerList.RemoveHandler(pair.Key, pair.Value[x]);
}
}
}
}
Я нашел этот ответ, и он почти соответствует моим потребностям. Спасибо SwDevMan81 за класс. Я модифицировал его, чтобы позволить подавление и возобновление отдельных методов, и решил опубликовать его здесь.
// This class allows you to selectively suppress event handlers for controls. You instantiate
// the suppressor object with the control, and after that you can use it to suppress all events
// or a single event. If you try to suppress an event which has already been suppressed
// it will be ignored. Same with resuming; you can resume all events which were suppressed,
// or a single one. If you try to resume an un-suppressed event handler, it will be ignored.
//cEventSuppressor _supButton1 = null;
//private cEventSuppressor SupButton1 {
// get {
// if (_supButton1 == null) {
// _supButton1 = new cEventSuppressor(this.button1);
// }
// return _supButton1;
// }
//}
//private void button1_Click(object sender, EventArgs e) {
// MessageBox.Show("Clicked!");
//}
//private void button2_Click(object sender, EventArgs e) {
// SupButton1.Suppress("button1_Click");
//}
//private void button3_Click(object sender, EventArgs e) {
// SupButton1.Resume("button1_Click");
//}
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Windows.Forms;
using System.ComponentModel;
namespace Crystal.Utilities {
public class cEventSuppressor {
Control _source;
EventHandlerList _sourceEventHandlerList;
FieldInfo _headFI;
Dictionary<object, Delegate[]> suppressedHandlers = new Dictionary<object, Delegate[]>();
PropertyInfo _sourceEventsInfo;
Type _eventHandlerListType;
Type _sourceType;
public cEventSuppressor(Control control) {
if (control == null)
throw new ArgumentNullException("control", "An instance of a control must be provided.");
_source = control;
_sourceType = _source.GetType();
_sourceEventsInfo = _sourceType.GetProperty("Events", BindingFlags.Instance | BindingFlags.NonPublic);
_sourceEventHandlerList = (EventHandlerList)_sourceEventsInfo.GetValue(_source, null);
_eventHandlerListType = _sourceEventHandlerList.GetType();
_headFI = _eventHandlerListType.GetField("head", BindingFlags.Instance | BindingFlags.NonPublic);
}
private Dictionary<object, Delegate[]> BuildList() {
Dictionary<object, Delegate[]> retval = new Dictionary<object, Delegate[]>();
object head = _headFI.GetValue(_sourceEventHandlerList);
if (head != null) {
Type listEntryType = head.GetType();
FieldInfo delegateFI = listEntryType.GetField("handler", BindingFlags.Instance | BindingFlags.NonPublic);
FieldInfo keyFI = listEntryType.GetField("key", BindingFlags.Instance | BindingFlags.NonPublic);
FieldInfo nextFI = listEntryType.GetField("next", BindingFlags.Instance | BindingFlags.NonPublic);
retval = BuildListWalk(retval, head, delegateFI, keyFI, nextFI);
}
return retval;
}
private Dictionary<object, Delegate[]> BuildListWalk(Dictionary<object, Delegate[]> dict,
object entry, FieldInfo delegateFI, FieldInfo keyFI, FieldInfo nextFI) {
if (entry != null) {
Delegate dele = (Delegate)delegateFI.GetValue(entry);
object key = keyFI.GetValue(entry);
object next = nextFI.GetValue(entry);
if (dele != null) {
Delegate[] listeners = dele.GetInvocationList();
if (listeners != null && listeners.Length > 0) {
dict.Add(key, listeners);
}
}
if (next != null) {
dict = BuildListWalk(dict, next, delegateFI, keyFI, nextFI);
}
}
return dict;
}
public void Resume() {
}
public void Resume(string pMethodName) {
//if (_handlers == null)
// throw new ApplicationException("Events have not been suppressed.");
Dictionary<object, Delegate[]> toRemove = new Dictionary<object, Delegate[]>();
// goes through all handlers which have been suppressed. If we are resuming,
// all handlers, or if we find the matching handler, add it back to the
// control's event handlers
foreach (KeyValuePair<object, Delegate[]> pair in suppressedHandlers) {
for (int x = 0; x < pair.Value.Length; x++) {
string methodName = pair.Value[x].Method.Name;
if (pMethodName == null || methodName.Equals(pMethodName)) {
_sourceEventHandlerList.AddHandler(pair.Key, pair.Value[x]);
toRemove.Add(pair.Key, pair.Value);
}
}
}
// remove all un-suppressed handlers from the list of suppressed handlers
foreach (KeyValuePair<object, Delegate[]> pair in toRemove) {
for (int x = 0; x < pair.Value.Length; x++) {
suppressedHandlers.Remove(pair.Key);
}
}
//_handlers = null;
}
public void Suppress() {
Suppress(null);
}
public void Suppress(string pMethodName) {
//if (_handlers != null)
// throw new ApplicationException("Events are already being suppressed.");
Dictionary<object, Delegate[]> dict = BuildList();
foreach (KeyValuePair<object, Delegate[]> pair in dict) {
for (int x = pair.Value.Length - 1; x >= 0; x--) {
//MethodInfo mi = pair.Value[x].Method;
//string s1 = mi.Name; // name of the method
//object o = pair.Value[x].Target;
// can use this to invoke method pair.Value[x].DynamicInvoke
string methodName = pair.Value[x].Method.Name;
if (pMethodName == null || methodName.Equals(pMethodName)) {
_sourceEventHandlerList.RemoveHandler(pair.Key, pair.Value[x]);
suppressedHandlers.Add(pair.Key, pair.Value);
}
}
}
}
}
}