I need to clear temporary the event sinks from another event and then restore them, but I don't know

S

Serge Shimanovsky

Hi,


I have a situation where I need to clear the event sinks from an event. But
let's say I don't know which methods (by name, I mean) signed up for that
event.


I do have a control with lets say two events: ItemCheck and
DataSourceChange. Callbacks assigned to ItemCheck and DataSourceChange
events at designtime.

The logic within DataSourceChanged callback requires temporary to disable
the ItemCheck which can be accomplished by smth. Like this:

private void controlX_DataSourceChanged(object sender, System.EventArgs e)

{

this.controlX.ItemCheck -= new
ItemCheckEventHandler(this.controlX_ItemCheck);

try

{

....

}

finally

{

this.controlX.ItemCheck += new
ItemCheckEventHandler(this.controlX_ItemCheck);

}

}

Now, the question is how to do the same thing without explicitly specifying
this.controlX_ItemCheck name? I'm looking for something like I was able to
do in Delphi, for example,

1) store the existing one to the local variable

2) assign this one to null

3) do some work here...

4) restore back to the one stored into local variable

I believe you know what I'm talking about.



I know I have to use reflection in .NET/C# in order to get this thing done,
but how?



P.S. Such things does not help because I have to specify the name of the
callback explicitly as well:

// EventInfo ei = (sender as MyControl).GetType().GetEvent("ItemCheck");

// Delegate d = Delegate.CreateDelegate(ei.EventHandlerType, this,
"controlX_ItemCheck");

ei.RemoveEventHandler(sender, d);

try

{

...

}

finally

{

ei.AddEventHandler(sender, d);

}



Thanks in advance,
Serge
 
I

Igor Zinkovsky [MSFT]

Hi Serge.

If you want to temporarily clear ALL listeners that have signed up for your
ItemCheck event - you can use the way that you've provided here (1. store
the delegate chain in a local variable, 2. set your ItemCheck event to
null, 3. do some work, 4. restore ItemCheck from your local copy):

private void controlX_DataSourceChanged(object sender, System.EventArgs e)
{
ItemCheckEventHandler tempCopy = this.controlX.ItemCheck;
this.controlX.ItemCheck = null;

try
{
....
}
finally
{
this.controlX.ItemCheck = tempCopy;
}
}


In addition, you need to be careful if your app is multithreaded. This is
to prevent situations when one thread has just removed all event listeners,
and another thread is trying to raise the event:

private void OnItemCheck()
{
ItemCheckEventHandler tempCopy = this.controlX.ItemCheck; // This
will create a new delegate chain since delegates are immutable
if(tempCopy != null)
tempCopy(this, Args);
}


Thanks,
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no warranties, and confers no rights.
Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm
 
S

Serge Shimanovsky

It would be nice, but doing this way I have the following error:

error CS0079: The
event 'DevExpress.XtraEditors.BaseCheckedListBoxControl.ItemCheck'
can only appear on the left hand side of += or -='

Any suggestions?

-Serge


Igor Zinkovsky said:
Hi Serge.

If you want to temporarily clear ALL listeners that have signed up for your
ItemCheck event - you can use the way that you've provided here (1. store
the delegate chain in a local variable, 2. set your ItemCheck event to
null, 3. do some work, 4. restore ItemCheck from your local copy):

private void controlX_DataSourceChanged(object sender, System.EventArgs e)
{
ItemCheckEventHandler tempCopy = this.controlX.ItemCheck;
this.controlX.ItemCheck = null;

try
{
....
}
finally
{
this.controlX.ItemCheck = tempCopy;
}
}


In addition, you need to be careful if your app is multithreaded. This is
to prevent situations when one thread has just removed all event listeners,
and another thread is trying to raise the event:

private void OnItemCheck()
{
ItemCheckEventHandler tempCopy = this.controlX.ItemCheck; // This
will create a new delegate chain since delegates are immutable
if(tempCopy != null)
tempCopy(this, Args);
}


Thanks,
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no warranties, and confers no rights.
Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm




Serge Shimanovsky said:
Hi,


I have a situation where I need to clear the event sinks from an event. But
let's say I don't know which methods (by name, I mean) signed up for that
event.


I do have a control with lets say two events: ItemCheck and
DataSourceChange. Callbacks assigned to ItemCheck and DataSourceChange
events at designtime.

The logic within DataSourceChanged callback requires temporary to disable
the ItemCheck which can be accomplished by smth. Like this:

private void controlX_DataSourceChanged(object sender, System.EventArgs e)

{

this.controlX.ItemCheck -= new
ItemCheckEventHandler(this.controlX_ItemCheck);

try

{

....

}

finally

{

this.controlX.ItemCheck += new
ItemCheckEventHandler(this.controlX_ItemCheck);

}

}

Now, the question is how to do the same thing without explicitly specifying
this.controlX_ItemCheck name? I'm looking for something like I was able to
do in Delphi, for example,

1) store the existing one to the local variable

2) assign this one to null

3) do some work here...

4) restore back to the one stored into local variable

I believe you know what I'm talking about.



I know I have to use reflection in .NET/C# in order to get this thing done,
but how?



P.S. Such things does not help because I have to specify the name of the
callback explicitly as well:

// EventInfo ei = (sender as MyControl).GetType().GetEvent("ItemCheck");

// Delegate d = Delegate.CreateDelegate(ei.EventHandlerType, this,
"controlX_ItemCheck");

ei.RemoveEventHandler(sender, d);

try

{

...

}

finally

{

ei.AddEventHandler(sender, d);

}



Thanks in advance,
Serge
 
I

Igor Zinkovsky [MSFT]

In your class (where ItemCheck is declared) you'll need to declare a private
delegate (to store listeners that sign up for ItemCheck event); provide
add/remove accessors for ItemCheck event; and add extra methods to
save/restore the event:

class ...
{
private ItemCheckEventHandler _ItemCheck;
private ItemCheckEventHandler _SavedItemCheck;

public event ItemCheckEventHandler ItemCheck
{
add
{
_ItemCheck += new ItemCheckEventHandler(value);
}

remove
{
_ItemCheck -= new ItemCheckEventHandler(value);
}
}

// The method that fires the event needs to be changed to trigger the
private _ItemCheck
protected virtual void OnItemCheck()
{
ItemCheckEventHandler tempCopy = _ItemCheck;
if(tempCopy != null)
tempCopy(this, Args);
}

public void ClearItemCheck()
{
_SavedItemCheck = _ItemCheck;
_ItemCheck = null;
}

public void RestoreItemCheck()
{
_ItemCheck = _SavedItemCheck;
}
}


Hope this helps.
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no warranties, and confers no rights.
Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm



Serge Shimanovsky said:
It would be nice, but doing this way I have the following error:

error CS0079: The
event 'DevExpress.XtraEditors.BaseCheckedListBoxControl.ItemCheck'
can only appear on the left hand side of += or -='

Any suggestions?

-Serge


Igor Zinkovsky said:
Hi Serge.

If you want to temporarily clear ALL listeners that have signed up for your
ItemCheck event - you can use the way that you've provided here (1. store
the delegate chain in a local variable, 2. set your ItemCheck event to
null, 3. do some work, 4. restore ItemCheck from your local copy):

private void controlX_DataSourceChanged(object sender, System.EventArgs e)
{
ItemCheckEventHandler tempCopy = this.controlX.ItemCheck;
this.controlX.ItemCheck = null;

try
{
....
}
finally
{
this.controlX.ItemCheck = tempCopy;
}
}


In addition, you need to be careful if your app is multithreaded. This is
to prevent situations when one thread has just removed all event listeners,
and another thread is trying to raise the event:

private void OnItemCheck()
{
ItemCheckEventHandler tempCopy = this.controlX.ItemCheck; // This
will create a new delegate chain since delegates are immutable
if(tempCopy != null)
tempCopy(this, Args);
}


Thanks,
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no warranties, and confers no rights.
Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm




Serge Shimanovsky said:
Hi,


I have a situation where I need to clear the event sinks from an
event.
But
let's say I don't know which methods (by name, I mean) signed up for that
event.


I do have a control with lets say two events: ItemCheck and
DataSourceChange. Callbacks assigned to ItemCheck and DataSourceChange
events at designtime.

The logic within DataSourceChanged callback requires temporary to disable
the ItemCheck which can be accomplished by smth. Like this:

private void controlX_DataSourceChanged(object sender,
System.EventArgs
able
 
S

Serge Shimanovsky

Igor,

Thank you very much. But the problem is that I'm using the DevExpress
components and don't have access to their implementation. I see how it
supoose to work, but lets say the situation I have right now. Is there any
other solution could be applied (I know the only way is to use reflection,
but how?)

-Serge


Igor Zinkovsky said:
In your class (where ItemCheck is declared) you'll need to declare a private
delegate (to store listeners that sign up for ItemCheck event); provide
add/remove accessors for ItemCheck event; and add extra methods to
save/restore the event:

class ...
{
private ItemCheckEventHandler _ItemCheck;
private ItemCheckEventHandler _SavedItemCheck;

public event ItemCheckEventHandler ItemCheck
{
add
{
_ItemCheck += new ItemCheckEventHandler(value);
}

remove
{
_ItemCheck -= new ItemCheckEventHandler(value);
}
}

// The method that fires the event needs to be changed to trigger the
private _ItemCheck
protected virtual void OnItemCheck()
{
ItemCheckEventHandler tempCopy = _ItemCheck;
if(tempCopy != null)
tempCopy(this, Args);
}

public void ClearItemCheck()
{
_SavedItemCheck = _ItemCheck;
_ItemCheck = null;
}

public void RestoreItemCheck()
{
_ItemCheck = _SavedItemCheck;
}
}


Hope this helps.
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no warranties, and confers no rights.
Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm



Serge Shimanovsky said:
It would be nice, but doing this way I have the following error:

error CS0079: The
event 'DevExpress.XtraEditors.BaseCheckedListBoxControl.ItemCheck'
can only appear on the left hand side of += or -='

Any suggestions?

-Serge
System.EventArgs
This
is
to prevent situations when one thread has just removed all event listeners,
and another thread is trying to raise the event:

private void OnItemCheck()
{
ItemCheckEventHandler tempCopy = this.controlX.ItemCheck;
//
This
will create a new delegate chain since delegates are immutable
if(tempCopy != null)
tempCopy(this, Args);
}


Thanks,
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no warranties, and confers no rights.
Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm




Hi,


I have a situation where I need to clear the event sinks from an event.
But
let's say I don't know which methods (by name, I mean) signed up for that
event.


I do have a control with lets say two events: ItemCheck and
DataSourceChange. Callbacks assigned to ItemCheck and DataSourceChange
events at designtime.

The logic within DataSourceChanged callback requires temporary to disable
the ItemCheck which can be accomplished by smth. Like this:

private void controlX_DataSourceChanged(object sender,
System.EventArgs
e)

{

this.controlX.ItemCheck -= new
ItemCheckEventHandler(this.controlX_ItemCheck);

try

{

....

}

finally

{

this.controlX.ItemCheck += new
ItemCheckEventHandler(this.controlX_ItemCheck);

}

}

Now, the question is how to do the same thing without explicitly
specifying
this.controlX_ItemCheck name? I'm looking for something like I was
able
to
do in Delphi, for example,

1) store the existing one to the local variable

2) assign this one to null

3) do some work here...

4) restore back to the one stored into local variable

I believe you know what I'm talking about.



I know I have to use reflection in .NET/C# in order to get this thing
done,
but how?



P.S. Such things does not help because I have to specify the name of the
callback explicitly as well:

// EventInfo ei = (sender as
MyControl).GetType().GetEvent("ItemCheck");

// Delegate d = Delegate.CreateDelegate(ei.EventHandlerType, this,
"controlX_ItemCheck");

ei.RemoveEventHandler(sender, d);

try

{

...

}

finally

{

ei.AddEventHandler(sender, d);

}



Thanks in advance,
Serge
 
I

Igor Zinkovsky [MSFT]

Serge, you can use the following, given that: (1) ItemCheck event is defined
in a way that caused the compiler to define a private delegate with the same
name (2) Class where ItemCheck is declared allows modification of private
members through reflection:

private void controlX_DataSourceChanged(object sender, System.EventArgs e)
{
FieldInfo f = this.controlX.GetType().GetField("ItemCheck",
BindingFlags.Instance| BindingFlags.NonPublic);
ItemCheckEventHandler tempCopy =
(ItemCheckEventHandler)f.GetValue(this.controlX);
f.SetValue(this.controlX, null);

try
{
....
}
finally
{
f.SetValue(this.controlX, tempCopy);
}
}


Thanks,
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no warranties, and confers no rights.
Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm


Serge Shimanovsky said:
Igor,

Thank you very much. But the problem is that I'm using the DevExpress
components and don't have access to their implementation. I see how it
supoose to work, but lets say the situation I have right now. Is there any
other solution could be applied (I know the only way is to use reflection,
but how?)

-Serge


Igor Zinkovsky said:
In your class (where ItemCheck is declared) you'll need to declare a private
delegate (to store listeners that sign up for ItemCheck event); provide
add/remove accessors for ItemCheck event; and add extra methods to
save/restore the event:

class ...
{
private ItemCheckEventHandler _ItemCheck;
private ItemCheckEventHandler _SavedItemCheck;

public event ItemCheckEventHandler ItemCheck
{
add
{
_ItemCheck += new ItemCheckEventHandler(value);
}

remove
{
_ItemCheck -= new ItemCheckEventHandler(value);
}
}

// The method that fires the event needs to be changed to trigger the
private _ItemCheck
protected virtual void OnItemCheck()
{
ItemCheckEventHandler tempCopy = _ItemCheck;
if(tempCopy != null)
tempCopy(this, Args);
}

public void ClearItemCheck()
{
_SavedItemCheck = _ItemCheck;
_ItemCheck = null;
}

public void RestoreItemCheck()
{
_ItemCheck = _SavedItemCheck;
}
}


Hope this helps.
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no warranties, and confers no rights.
Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm



Serge Shimanovsky said:
It would be nice, but doing this way I have the following error:

error CS0079: The
event 'DevExpress.XtraEditors.BaseCheckedListBoxControl.ItemCheck'
can only appear on the left hand side of += or -='

Any suggestions?

-Serge


message Hi Serge.

If you want to temporarily clear ALL listeners that have signed up for
your
ItemCheck event - you can use the way that you've provided here (1. store
the delegate chain in a local variable, 2. set your ItemCheck event to
null, 3. do some work, 4. restore ItemCheck from your local copy):

private void controlX_DataSourceChanged(object sender,
System.EventArgs
e)
{
ItemCheckEventHandler tempCopy = this.controlX.ItemCheck;
this.controlX.ItemCheck = null;

try
{
....
}
finally
{
this.controlX.ItemCheck = tempCopy;
}
}


In addition, you need to be careful if your app is multithreaded.
This
is
to prevent situations when one thread has just removed all event
listeners,
and another thread is trying to raise the event:

private void OnItemCheck()
{
ItemCheckEventHandler tempCopy = this.controlX.ItemCheck; //
This
will create a new delegate chain since delegates are immutable
if(tempCopy != null)
tempCopy(this, Args);
}


Thanks,
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no warranties, and confers no
rights.
Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm




Hi,


I have a situation where I need to clear the event sinks from an event.
But
let's say I don't know which methods (by name, I mean) signed up for
that
event.


I do have a control with lets say two events: ItemCheck and
DataSourceChange. Callbacks assigned to ItemCheck and DataSourceChange
events at designtime.

The logic within DataSourceChanged callback requires temporary to
disable
the ItemCheck which can be accomplished by smth. Like this:

private void controlX_DataSourceChanged(object sender, System.EventArgs
e)

{

this.controlX.ItemCheck -= new
ItemCheckEventHandler(this.controlX_ItemCheck);

try

{

....

}

finally

{

this.controlX.ItemCheck += new
ItemCheckEventHandler(this.controlX_ItemCheck);

}

}

Now, the question is how to do the same thing without explicitly
specifying
this.controlX_ItemCheck name? I'm looking for something like I was able
to
do in Delphi, for example,

1) store the existing one to the local variable

2) assign this one to null

3) do some work here...

4) restore back to the one stored into local variable

I believe you know what I'm talking about.



I know I have to use reflection in .NET/C# in order to get this thing
done,
but how?



P.S. Such things does not help because I have to specify the name
of
the
callback explicitly as well:

// EventInfo ei = (sender as
MyControl).GetType().GetEvent("ItemCheck");

// Delegate d = Delegate.CreateDelegate(ei.EventHandlerType, this,
"controlX_ItemCheck");

ei.RemoveEventHandler(sender, d);

try

{

...

}

finally

{

ei.AddEventHandler(sender, d);

}



Thanks in advance,
Serge
 
S

Serge Shimanovsky

Igor,

This is Ok as well as they have declaration of this handler in this class,
but they do have this in the base class, so GetField() and .SetValue() would
not work. Isn't it?

-Serge


Igor Zinkovsky said:
Serge, you can use the following, given that: (1) ItemCheck event is defined
in a way that caused the compiler to define a private delegate with the same
name (2) Class where ItemCheck is declared allows modification of private
members through reflection:

private void controlX_DataSourceChanged(object sender, System.EventArgs e)
{
FieldInfo f = this.controlX.GetType().GetField("ItemCheck",
BindingFlags.Instance| BindingFlags.NonPublic);
ItemCheckEventHandler tempCopy =
(ItemCheckEventHandler)f.GetValue(this.controlX);
f.SetValue(this.controlX, null);

try
{
....
}
finally
{
f.SetValue(this.controlX, tempCopy);
}
}


Thanks,
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no warranties, and confers no rights.
Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm


Serge Shimanovsky said:
Igor,

Thank you very much. But the problem is that I'm using the DevExpress
components and don't have access to their implementation. I see how it
supoose to work, but lets say the situation I have right now. Is there any
other solution could be applied (I know the only way is to use reflection,
but how?)

-Serge


Igor Zinkovsky said:
In your class (where ItemCheck is declared) you'll need to declare a private
delegate (to store listeners that sign up for ItemCheck event); provide
add/remove accessors for ItemCheck event; and add extra methods to
save/restore the event:

class ...
{
private ItemCheckEventHandler _ItemCheck;
private ItemCheckEventHandler _SavedItemCheck;

public event ItemCheckEventHandler ItemCheck
{
add
{
_ItemCheck += new ItemCheckEventHandler(value);
}

remove
{
_ItemCheck -= new ItemCheckEventHandler(value);
}
}

// The method that fires the event needs to be changed to trigger the
private _ItemCheck
protected virtual void OnItemCheck()
{
ItemCheckEventHandler tempCopy = _ItemCheck;
if(tempCopy != null)
tempCopy(this, Args);
}

public void ClearItemCheck()
{
_SavedItemCheck = _ItemCheck;
_ItemCheck = null;
}

public void RestoreItemCheck()
{
_ItemCheck = _SavedItemCheck;
}
}


Hope this helps.
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no warranties, and confers no rights.
Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm



It would be nice, but doing this way I have the following error:

error CS0079: The
event 'DevExpress.XtraEditors.BaseCheckedListBoxControl.ItemCheck'
can only appear on the left hand side of += or -='

Any suggestions?

-Serge


message Hi Serge.

If you want to temporarily clear ALL listeners that have signed up for
your
ItemCheck event - you can use the way that you've provided here (1.
store
the delegate chain in a local variable, 2. set your ItemCheck
event
to
null, 3. do some work, 4. restore ItemCheck from your local copy):

private void controlX_DataSourceChanged(object sender, System.EventArgs
e)
{
ItemCheckEventHandler tempCopy = this.controlX.ItemCheck;
this.controlX.ItemCheck = null;

try
{
....
}
finally
{
this.controlX.ItemCheck = tempCopy;
}
}


In addition, you need to be careful if your app is multithreaded. This
is
to prevent situations when one thread has just removed all event
listeners,
and another thread is trying to raise the event:

private void OnItemCheck()
{
ItemCheckEventHandler tempCopy = this.controlX.ItemCheck; //
This
will create a new delegate chain since delegates are immutable
if(tempCopy != null)
tempCopy(this, Args);
}


Thanks,
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no warranties, and confers no
rights.
Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm




Hi,


I have a situation where I need to clear the event sinks from an
event.
But
let's say I don't know which methods (by name, I mean) signed up for
that
event.


I do have a control with lets say two events: ItemCheck and
DataSourceChange. Callbacks assigned to ItemCheck and DataSourceChange
events at designtime.

The logic within DataSourceChanged callback requires temporary to
disable
the ItemCheck which can be accomplished by smth. Like this:

private void controlX_DataSourceChanged(object sender,
System.EventArgs
e)

{

this.controlX.ItemCheck -= new
ItemCheckEventHandler(this.controlX_ItemCheck);

try

{

....

}

finally

{

this.controlX.ItemCheck += new
ItemCheckEventHandler(this.controlX_ItemCheck);

}

}

Now, the question is how to do the same thing without explicitly
specifying
this.controlX_ItemCheck name? I'm looking for something like I was
able
to
do in Delphi, for example,

1) store the existing one to the local variable

2) assign this one to null

3) do some work here...

4) restore back to the one stored into local variable

I believe you know what I'm talking about.



I know I have to use reflection in .NET/C# in order to get this thing
done,
but how?



P.S. Such things does not help because I have to specify the
name
 
I

Igor Zinkovsky [MSFT]

Serge,

If I understand correctly, "ItemCheck" event is declared in some base class,
and the class of controlX derives from that base class?

If this is correct - try using the "BaseType" property of the controlX's
type to get the type of the base class:

FieldInfo f = this.controlX.GetType().BaseType.GetField("ItemCheck",
BindingFlags.Instance| BindingFlags.NonPublic);

Thanks,
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no warranties, and confers no rights.
Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm


Serge Shimanovsky said:
Igor,

This is Ok as well as they have declaration of this handler in this class,
but they do have this in the base class, so GetField() and .SetValue() would
not work. Isn't it?

-Serge


Igor Zinkovsky said:
Serge, you can use the following, given that: (1) ItemCheck event is defined
in a way that caused the compiler to define a private delegate with the same
name (2) Class where ItemCheck is declared allows modification of private
members through reflection:

private void controlX_DataSourceChanged(object sender, System.EventArgs e)
{
FieldInfo f = this.controlX.GetType().GetField("ItemCheck",
BindingFlags.Instance| BindingFlags.NonPublic);
ItemCheckEventHandler tempCopy =
(ItemCheckEventHandler)f.GetValue(this.controlX);
f.SetValue(this.controlX, null);

try
{
....
}
finally
{
f.SetValue(this.controlX, tempCopy);
}
}


Thanks,
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no warranties, and confers no rights.
Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm


Serge Shimanovsky said:
Igor,

Thank you very much. But the problem is that I'm using the DevExpress
components and don't have access to their implementation. I see how it
supoose to work, but lets say the situation I have right now. Is there any
other solution could be applied (I know the only way is to use reflection,
but how?)

-Serge


message In your class (where ItemCheck is declared) you'll need to declare a
private
delegate (to store listeners that sign up for ItemCheck event); provide
add/remove accessors for ItemCheck event; and add extra methods to
save/restore the event:

class ...
{
private ItemCheckEventHandler _ItemCheck;
private ItemCheckEventHandler _SavedItemCheck;

public event ItemCheckEventHandler ItemCheck
{
add
{
_ItemCheck += new ItemCheckEventHandler(value);
}

remove
{
_ItemCheck -= new ItemCheckEventHandler(value);
}
}

// The method that fires the event needs to be changed to
trigger
the
private _ItemCheck
protected virtual void OnItemCheck()
{
ItemCheckEventHandler tempCopy = _ItemCheck;
if(tempCopy != null)
tempCopy(this, Args);
}

public void ClearItemCheck()
{
_SavedItemCheck = _ItemCheck;
_ItemCheck = null;
}

public void RestoreItemCheck()
{
_ItemCheck = _SavedItemCheck;
}
}


Hope this helps.
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no warranties, and confers no
rights.
Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm



It would be nice, but doing this way I have the following error:

error CS0079: The
event
'DevExpress.XtraEditors.BaseCheckedListBoxControl.ItemCheck'
can only appear on the left hand side of += or -='

Any suggestions?

-Serge


"Igor Zinkovsky [MSFT]" <[email protected]>
wrote
in
message Hi Serge.

If you want to temporarily clear ALL listeners that have signed
up
for
your
ItemCheck event - you can use the way that you've provided here (1.
store
the delegate chain in a local variable, 2. set your ItemCheck event
to
null, 3. do some work, 4. restore ItemCheck from your local copy):

private void controlX_DataSourceChanged(object sender,
System.EventArgs
e)
{
ItemCheckEventHandler tempCopy = this.controlX.ItemCheck;
this.controlX.ItemCheck = null;

try
{
....
}
finally
{
this.controlX.ItemCheck = tempCopy;
}
}


In addition, you need to be careful if your app is multithreaded.
This
is
to prevent situations when one thread has just removed all event
listeners,
and another thread is trying to raise the event:

private void OnItemCheck()
{
ItemCheckEventHandler tempCopy = this.controlX.ItemCheck;
//
This
will create a new delegate chain since delegates are immutable
if(tempCopy != null)
tempCopy(this, Args);
}


Thanks,
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no warranties, and confers no
rights.
Use of included script samples are subject to the terms
specified
at up
for name
 
S

Serge Shimanovsky

Igor,

I know. But this does not work either. Both of them return NULL.

They have declaration smth. like this:
----------------------------------------------------------------------------
--------------------
public abstract class BaseControl : BaseGrandparentControl
{
...
private readonly object itemCheckID = new object();

public event ItemCheckEventHandler ItemCheck {
add { Events.AddHandler(itemCheckID, value); }
remove { Events.RemoveHandler(itemCheckID, value); }
}
public delegate void ItemCheckEventHandler(object sender,
ItemCheckEventArgs e);

.....

protected virtual void RaiseItemCheck(ItemCheckEventArgs e) {
ItemCheckEventHandler handler =
(ItemCheckEventHandler)Events[itemCheckID];
if(handler != null) handler(this, e);
}

}

public class controlX : BaseControl {

}


So, the
FieldInfo f =
this.controlX.GetType().BaseType.GetField("ItemCheck",
BindingFlags.Instance| BindingFlags.NonPublic);
or
FieldInfo f =
this.controlX.GetType().BaseType.GetField("ItemCheck",
BindingFlags.Instance| BindingFlags.Public);

return NULL. Any ideas?

-Serge

----------------------------------------------------------------------------
---------------------------
Igor Zinkovsky said:
Serge,

If I understand correctly, "ItemCheck" event is declared in some base class,
and the class of controlX derives from that base class?

If this is correct - try using the "BaseType" property of the controlX's
type to get the type of the base class:

FieldInfo f = this.controlX.GetType().BaseType.GetField("ItemCheck",
BindingFlags.Instance| BindingFlags.NonPublic);

Thanks,
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no warranties, and confers no rights.
Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm


Serge Shimanovsky said:
Igor,

This is Ok as well as they have declaration of this handler in this class,
but they do have this in the base class, so GetField() and .SetValue() would
not work. Isn't it?

-Serge


the
same
System.EventArgs
e)
{
FieldInfo f = this.controlX.GetType().GetField("ItemCheck",
BindingFlags.Instance| BindingFlags.NonPublic);
ItemCheckEventHandler tempCopy =
(ItemCheckEventHandler)f.GetValue(this.controlX);
f.SetValue(this.controlX, null);

try
{
....
}
finally
{
f.SetValue(this.controlX, tempCopy);
}
}


Thanks,
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no warranties, and confers no rights.
Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm


Igor,

Thank you very much. But the problem is that I'm using the DevExpress
components and don't have access to their implementation. I see how it
supoose to work, but lets say the situation I have right now. Is
there
any
other solution could be applied (I know the only way is to use reflection,
but how?)

-Serge


message In your class (where ItemCheck is declared) you'll need to declare a
private
delegate (to store listeners that sign up for ItemCheck event); provide
add/remove accessors for ItemCheck event; and add extra methods to
save/restore the event:

class ...
{
private ItemCheckEventHandler _ItemCheck;
private ItemCheckEventHandler _SavedItemCheck;

public event ItemCheckEventHandler ItemCheck
{
add
{
_ItemCheck += new ItemCheckEventHandler(value);
}

remove
{
_ItemCheck -= new ItemCheckEventHandler(value);
}
}

// The method that fires the event needs to be changed to trigger
the
private _ItemCheck
protected virtual void OnItemCheck()
{
ItemCheckEventHandler tempCopy = _ItemCheck;
if(tempCopy != null)
tempCopy(this, Args);
}

public void ClearItemCheck()
{
_SavedItemCheck = _ItemCheck;
_ItemCheck = null;
}

public void RestoreItemCheck()
{
_ItemCheck = _SavedItemCheck;
}
}


Hope this helps.
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no warranties, and confers no
rights.
Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm



It would be nice, but doing this way I have the following error:

error CS0079: The
event
'DevExpress.XtraEditors.BaseCheckedListBoxControl.ItemCheck'
can only appear on the left hand side of += or -='

Any suggestions?

-Serge


in
message Hi Serge.

If you want to temporarily clear ALL listeners that have
signed
up
for
your
ItemCheck event - you can use the way that you've provided
here
(1.
store
the delegate chain in a local variable, 2. set your ItemCheck event
to
null, 3. do some work, 4. restore ItemCheck from your local copy):

private void controlX_DataSourceChanged(object sender,
System.EventArgs
e)
{
ItemCheckEventHandler tempCopy = this.controlX.ItemCheck;
this.controlX.ItemCheck = null;

try
{
....
}
finally
{
this.controlX.ItemCheck = tempCopy;
}
}


In addition, you need to be careful if your app is multithreaded.
This
is
to prevent situations when one thread has just removed all event
listeners,
and another thread is trying to raise the event:

private void OnItemCheck()
{
ItemCheckEventHandler tempCopy = this.controlX.ItemCheck;
//
This
will create a new delegate chain since delegates are immutable
if(tempCopy != null)
tempCopy(this, Args);
}


Thanks,
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no warranties, and
confers
no
rights.
Use of included script samples are subject to the terms
specified
at
http://www.microsoft.com/info/cpyright.htm




Hi,


I have a situation where I need to clear the event sinks
from
signed
up temporary
to I
was
 
I

Igor Zinkovsky [MSFT]

Serge,

The 1st condition "((1) ItemCheck event is defined in a way that caused the
compiler to define a private delegate with the same name)" was making an
assumption that the BaseControl class did not use accessors in defining
ItemCheck event. The assumption was relying on the compiler declaring a
private delegate with "ItemCheck" name. Since BaseControl does use
accessors for ItemCheck event - we can no longer assume that there is going
to be a private delegate with "ItemCheck" name.

Do you know any implementation details about the class for which you have
"Events" member in BaseControl?

Looking at the code you provided below, I am assuming that the class has an
internal data structure (array ?) that contains a list of delegate chains,
which are obtained through an indexer (based on itemCheckID). Without
knowing more about that data structure you can't reflect on the specific
ItemCheckEventHandler reference (that points to the delegate chain) in order
to temporarily set it to null.


Thanks,
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no warranties, and confers no rights.
Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm




Serge Shimanovsky said:
Igor,

I know. But this does not work either. Both of them return NULL.

They have declaration smth. like this:
-------------------------------------------------------------------------- --
--------------------
public abstract class BaseControl : BaseGrandparentControl
{
...
private readonly object itemCheckID = new object();

public event ItemCheckEventHandler ItemCheck {
add { Events.AddHandler(itemCheckID, value); }
remove { Events.RemoveHandler(itemCheckID, value); }
}
public delegate void ItemCheckEventHandler(object sender,
ItemCheckEventArgs e);

....

protected virtual void RaiseItemCheck(ItemCheckEventArgs e) {
ItemCheckEventHandler handler =
(ItemCheckEventHandler)Events[itemCheckID];
if(handler != null) handler(this, e);
}

}

public class controlX : BaseControl {

}


So, the
FieldInfo f =
this.controlX.GetType().BaseType.GetField("ItemCheck",
BindingFlags.Instance| BindingFlags.NonPublic);
or
FieldInfo f =
this.controlX.GetType().BaseType.GetField("ItemCheck",
BindingFlags.Instance| BindingFlags.Public);

return NULL. Any ideas?

-Serge

-------------------------------------------------------------------------- --
---------------------------
Igor Zinkovsky said:
Serge,

If I understand correctly, "ItemCheck" event is declared in some base class,
and the class of controlX derives from that base class?

If this is correct - try using the "BaseType" property of the controlX's
type to get the type of the base class:

FieldInfo f = this.controlX.GetType().BaseType.GetField("ItemCheck",
BindingFlags.Instance| BindingFlags.NonPublic);

Thanks,
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no warranties, and confers no rights.
Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm


Serge Shimanovsky said:
Igor,

This is Ok as well as they have declaration of this handler in this class,
but they do have this in the base class, so GetField() and .SetValue() would
not work. Isn't it?

-Serge


message Serge, you can use the following, given that: (1) ItemCheck event is
defined
in a way that caused the compiler to define a private delegate with the
same
name (2) Class where ItemCheck is declared allows modification of private
members through reflection:

private void controlX_DataSourceChanged(object sender,
System.EventArgs
e)
{
FieldInfo f = this.controlX.GetType().GetField("ItemCheck",
BindingFlags.Instance| BindingFlags.NonPublic);
ItemCheckEventHandler tempCopy =
(ItemCheckEventHandler)f.GetValue(this.controlX);
f.SetValue(this.controlX, null);

try
{
....
}
finally
{
f.SetValue(this.controlX, tempCopy);
}
}


Thanks,
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no warranties, and confers no
rights.
Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm


Igor,

Thank you very much. But the problem is that I'm using the DevExpress
components and don't have access to their implementation. I see
how
it
supoose to work, but lets say the situation I have right now. Is there
any
other solution could be applied (I know the only way is to use
reflection,
but how?)

-Serge


"Igor Zinkovsky [MSFT]" <[email protected]>
wrote
in
message In your class (where ItemCheck is declared) you'll need to
declare
a
private
delegate (to store listeners that sign up for ItemCheck event);
provide
add/remove accessors for ItemCheck event; and add extra methods to
save/restore the event:

class ...
{
private ItemCheckEventHandler _ItemCheck;
private ItemCheckEventHandler _SavedItemCheck;

public event ItemCheckEventHandler ItemCheck
{
add
{
_ItemCheck += new ItemCheckEventHandler(value);
}

remove
{
_ItemCheck -= new ItemCheckEventHandler(value);
}
}

// The method that fires the event needs to be changed to trigger
the
private _ItemCheck
protected virtual void OnItemCheck()
{
ItemCheckEventHandler tempCopy = _ItemCheck;
if(tempCopy != null)
tempCopy(this, Args);
}

public void ClearItemCheck()
{
_SavedItemCheck = _ItemCheck;
_ItemCheck = null;
}

public void RestoreItemCheck()
{
_ItemCheck = _SavedItemCheck;
}
}


Hope this helps.
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no warranties, and confers no
rights.
Use of included script samples are subject to the terms
specified
at
http://www.microsoft.com/info/cpyright.htm



It would be nice, but doing this way I have the following error:

error CS0079: The
event
'DevExpress.XtraEditors.BaseCheckedListBoxControl.ItemCheck'
can only appear on the left hand side of += or -='

Any suggestions?

-Serge


in
message Hi Serge.

If you want to temporarily clear ALL listeners that have
signed
up
for
your
ItemCheck event - you can use the way that you've provided here
(1.
store
the delegate chain in a local variable, 2. set your ItemCheck
event
to
null, 3. do some work, 4. restore ItemCheck from your local copy):

private void controlX_DataSourceChanged(object sender,
System.EventArgs
e)
{
ItemCheckEventHandler tempCopy = this.controlX.ItemCheck;
this.controlX.ItemCheck = null;

try
{
....
}
finally
{
this.controlX.ItemCheck = tempCopy;
}
}


In addition, you need to be careful if your app is multithreaded.
This
is
to prevent situations when one thread has just removed all event
listeners,
and another thread is trying to raise the event:

private void OnItemCheck()
{
ItemCheckEventHandler tempCopy = this.controlX.ItemCheck;
//
This
will create a new delegate chain since delegates are immutable
if(tempCopy != null)
tempCopy(this, Args);
}


Thanks,
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no warranties, and confers
no
rights.
Use of included script samples are subject to the terms specified
at
http://www.microsoft.com/info/cpyright.htm




message
Hi,


I have a situation where I need to clear the event sinks
from
an
event.
But
let's say I don't know which methods (by name, I mean)
signed
up
for
that
event.


I do have a control with lets say two events: ItemCheck and
DataSourceChange. Callbacks assigned to ItemCheck and
DataSourceChange
events at designtime.

The logic within DataSourceChanged callback requires temporary
to
disable
the ItemCheck which can be accomplished by smth. Like this:

private void controlX_DataSourceChanged(object sender,
System.EventArgs
e)

{

this.controlX.ItemCheck -= new
ItemCheckEventHandler(this.controlX_ItemCheck);

try

{

....

}

finally

{

this.controlX.ItemCheck += new
ItemCheckEventHandler(this.controlX_ItemCheck);

}

}

Now, the question is how to do the same thing without explicitly
specifying
this.controlX_ItemCheck name? I'm looking for something
like
 
S

Serge Shimanovsky

Igor,

based on ILDasm RaiseItemCheck/add_itemCheck/remove_itemCheck (see the code
snippet in prev. reply), it takes Events[] from ComponentModel, so I don;t
believe they have internal array of delegates.

============================================================================
=================================

..method family hidebysig newslot virtual

instance void RaiseItemCheck(class
DevExpress.XtraEditors.Controls.ItemCheckEventArgs e) cil managed

{

// Code size 35 (0x23)

..maxstack 3

..locals init (class DevExpress.XtraEditors.Controls.ItemCheckEventHandler
V_0)

IL_0000: ldarg.0

IL_0001: call instance class [System]System.ComponentModel.EventHandlerList
[System]System.ComponentModel.Component::get_Events()

IL_0006: ldarg.0

IL_0007: ldfld object
DevExpress.XtraEditors.BaseCheckedListBoxControl::itemCheckID

IL_000c: callvirt instance class [mscorlib]System.Delegate
[System]System.ComponentModel.EventHandlerList::get_Item(object)

IL_0011: castclass DevExpress.XtraEditors.Controls.ItemCheckEventHandler

IL_0016: stloc.0

IL_0017: ldloc.0

IL_0018: brfalse.s IL_0022

IL_001a: ldloc.0

IL_001b: ldarg.0

IL_001c: ldarg.1

IL_001d: callvirt instance void
DevExpress.XtraEditors.Controls.ItemCheckEventHandler::Invoke(object,

class DevExpress.XtraEditors.Controls.ItemCheckEventArgs)

IL_0022: ret

} // end of method BaseCheckedListBoxControl::RaiseItemCheck



..method public hidebysig specialname instance void

add_ItemCheck(class DevExpress.XtraEditors.Controls.ItemCheckEventHandler
'value') cil managed

{

// Code size 19 (0x13)

..maxstack 3

IL_0000: ldarg.0

IL_0001: call instance class [System]System.ComponentModel.EventHandlerList
[System]System.ComponentModel.Component::get_Events()

IL_0006: ldarg.0

IL_0007: ldfld object
DevExpress.XtraEditors.BaseCheckedListBoxControl::itemCheckID

IL_000c: ldarg.1

IL_000d: callvirt instance void
[System]System.ComponentModel.EventHandlerList::AddHandler(object,

class [mscorlib]System.Delegate)

IL_0012: ret

} // end of method BaseCheckedListBoxControl::add_ItemCheck



..method public hidebysig specialname instance void

remove_ItemCheck(class DevExpress.XtraEditors.Controls.ItemCheckEventHandler
'value') cil managed

{

// Code size 19 (0x13)

..maxstack 3

IL_0000: ldarg.0

IL_0001: call instance class [System]System.ComponentModel.EventHandlerList
[System]System.ComponentModel.Component::get_Events()

IL_0006: ldarg.0

IL_0007: ldfld object
DevExpress.XtraEditors.BaseCheckedListBoxControl::itemCheckID

IL_000c: ldarg.1

IL_000d: callvirt instance void
[System]System.ComponentModel.EventHandlerList::RemoveHandler(object,

class [mscorlib]System.Delegate)

IL_0012: ret

} // end of method BaseCheckedListBoxControl::remove_ItemCheck



============================================================================
=================================

-Serge





Igor Zinkovsky said:
Serge,

The 1st condition "((1) ItemCheck event is defined in a way that caused the
compiler to define a private delegate with the same name)" was making an
assumption that the BaseControl class did not use accessors in defining
ItemCheck event. The assumption was relying on the compiler declaring a
private delegate with "ItemCheck" name. Since BaseControl does use
accessors for ItemCheck event - we can no longer assume that there is going
to be a private delegate with "ItemCheck" name.

Do you know any implementation details about the class for which you have
"Events" member in BaseControl?

Looking at the code you provided below, I am assuming that the class has an
internal data structure (array ?) that contains a list of delegate chains,
which are obtained through an indexer (based on itemCheckID). Without
knowing more about that data structure you can't reflect on the specific
ItemCheckEventHandler reference (that points to the delegate chain) in order
to temporarily set it to null.


Thanks,
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no warranties, and confers no rights.
Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm




Serge Shimanovsky said:
Igor,

I know. But this does not work either. Both of them return NULL.

They have declaration smth. like this:
--------------------------------------------------------------------------
--
--------------------
public abstract class BaseControl : BaseGrandparentControl
{
...
private readonly object itemCheckID = new object();

public event ItemCheckEventHandler ItemCheck {
add { Events.AddHandler(itemCheckID, value); }
remove { Events.RemoveHandler(itemCheckID, value); }
}
public delegate void ItemCheckEventHandler(object sender,
ItemCheckEventArgs e);

....

protected virtual void RaiseItemCheck(ItemCheckEventArgs e) {
ItemCheckEventHandler handler =
(ItemCheckEventHandler)Events[itemCheckID];
if(handler != null) handler(this, e);
}

}

public class controlX : BaseControl {

}


So, the
FieldInfo f =
this.controlX.GetType().BaseType.GetField("ItemCheck",
BindingFlags.Instance| BindingFlags.NonPublic);
or
FieldInfo f =
this.controlX.GetType().BaseType.GetField("ItemCheck",
BindingFlags.Instance| BindingFlags.Public);

return NULL. Any ideas?

-Serge

--------------------------------------------------------------------------
--
---------------------------
Igor Zinkovsky said:
Serge,

If I understand correctly, "ItemCheck" event is declared in some base class,
and the class of controlX derives from that base class?

If this is correct - try using the "BaseType" property of the controlX's
type to get the type of the base class:

FieldInfo f = this.controlX.GetType().BaseType.GetField("ItemCheck",
BindingFlags.Instance| BindingFlags.NonPublic);

Thanks,
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no warranties, and confers no rights.
Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm


Igor,

This is Ok as well as they have declaration of this handler in this class,
but they do have this in the base class, so GetField() and ..SetValue()
would
not work. Isn't it?

-Serge


message Serge, you can use the following, given that: (1) ItemCheck event is
defined
in a way that caused the compiler to define a private delegate
with
the
same
name (2) Class where ItemCheck is declared allows modification of
private
members through reflection:

private void controlX_DataSourceChanged(object sender, System.EventArgs
e)
{
FieldInfo f = this.controlX.GetType().GetField("ItemCheck",
BindingFlags.Instance| BindingFlags.NonPublic);
ItemCheckEventHandler tempCopy =
(ItemCheckEventHandler)f.GetValue(this.controlX);
f.SetValue(this.controlX, null);

try
{
....
}
finally
{
f.SetValue(this.controlX, tempCopy);
}
}


Thanks,
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no warranties, and confers no
rights.
Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm


Igor,

Thank you very much. But the problem is that I'm using the DevExpress
components and don't have access to their implementation. I see
how
it
supoose to work, but lets say the situation I have right now. Is there
any
other solution could be applied (I know the only way is to use
reflection,
but how?)

-Serge


in
message In your class (where ItemCheck is declared) you'll need to
declare
a
private
delegate (to store listeners that sign up for ItemCheck event);
provide
add/remove accessors for ItemCheck event; and add extra
methods
to
save/restore the event:

class ...
{
private ItemCheckEventHandler _ItemCheck;
private ItemCheckEventHandler _SavedItemCheck;

public event ItemCheckEventHandler ItemCheck
{
add
{
_ItemCheck += new ItemCheckEventHandler(value);
}

remove
{
_ItemCheck -= new ItemCheckEventHandler(value);
}
}

// The method that fires the event needs to be changed to
trigger
the
private _ItemCheck
protected virtual void OnItemCheck()
{
ItemCheckEventHandler tempCopy = _ItemCheck;
if(tempCopy != null)
tempCopy(this, Args);
}

public void ClearItemCheck()
{
_SavedItemCheck = _ItemCheck;
_ItemCheck = null;
}

public void RestoreItemCheck()
{
_ItemCheck = _SavedItemCheck;
}
}


Hope this helps.
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no warranties, and
confers
no
rights.
Use of included script samples are subject to the terms
specified
at
http://www.microsoft.com/info/cpyright.htm



It would be nice, but doing this way I have the following error:

error CS0079: The
event
'DevExpress.XtraEditors.BaseCheckedListBoxControl.ItemCheck'
can only appear on the left hand side of += or -='

Any suggestions?

-Serge


"Igor Zinkovsky [MSFT]"
wrote
in
message Hi Serge.

If you want to temporarily clear ALL listeners that have signed
up
for
your
ItemCheck event - you can use the way that you've provided here
(1.
store
the delegate chain in a local variable, 2. set your ItemCheck
event
to
null, 3. do some work, 4. restore ItemCheck from your local
copy):

private void controlX_DataSourceChanged(object sender,
System.EventArgs
e)
{
ItemCheckEventHandler tempCopy = this.controlX.ItemCheck;
this.controlX.ItemCheck = null;

try
{
....
}
finally
{
this.controlX.ItemCheck = tempCopy;
}
}


In addition, you need to be careful if your app is
multithreaded.
This
is
to prevent situations when one thread has just removed all event
listeners,
and another thread is trying to raise the event:

private void OnItemCheck()
{
ItemCheckEventHandler tempCopy = this.controlX.ItemCheck;
//
This
will create a new delegate chain since delegates are immutable
if(tempCopy != null)
tempCopy(this, Args);
}


Thanks,
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no warranties, and confers
no
rights.
Use of included script samples are subject to the terms
specified
at
http://www.microsoft.com/info/cpyright.htm




message
Hi,


I have a situation where I need to clear the event sinks from
an
event.
But
let's say I don't know which methods (by name, I mean) signed
up
for
that
event.


I do have a control with lets say two events: ItemCheck and
DataSourceChange. Callbacks assigned to ItemCheck and
DataSourceChange
events at designtime.

The logic within DataSourceChanged callback requires temporary
to
disable
the ItemCheck which can be accomplished by smth. Like this:

private void controlX_DataSourceChanged(object sender,
System.EventArgs
e)

{

this.controlX.ItemCheck -= new
ItemCheckEventHandler(this.controlX_ItemCheck);

try

{

....

}

finally

{

this.controlX.ItemCheck += new
ItemCheckEventHandler(this.controlX_ItemCheck);

}

}

Now, the question is how to do the same thing without
explicitly
specifying
this.controlX_ItemCheck name? I'm looking for something
like
I
was
able
to
do in Delphi, for example,

1) store the existing one to the local variable

2) assign this one to null

3) do some work here...

4) restore back to the one stored into local variable

I believe you know what I'm talking about.



I know I have to use reflection in .NET/C# in order to get
this
thing
done,
but how?



P.S. Such things does not help because I have to specify the
name
of
the
callback explicitly as well:

// EventInfo ei = (sender as
MyControl).GetType().GetEvent("ItemCheck");

// Delegate d =
Delegate.CreateDelegate(ei.EventHandlerType,
this,
"controlX_ItemCheck");

ei.RemoveEventHandler(sender, d);

try

{

...

}

finally

{

ei.AddEventHandler(sender, d);

}



Thanks in advance,
Serge
 
I

Igor Zinkovsky [MSFT]

Serge,

It looks like Events is an instance of
System.ComponentModel.EventHandlerList.

The following should work for you:

private void controlX_DataSourceChanged(object sender,System.EventArgs e)
{
// Get the reference to BaseControl.itemCheckID
FieldInfo fieldItemCheckID =
this.controlX.GetType().BaseType.GetField("itemCheckID",
BindingFlags.Instance| BindingFlags.NonPublic);
object itemCheckID = FieldItemCheckID.GetValue(this.controlX);

// Save the delegate
FieldInfo fieldEvents =
this.controlX.GetType().BaseType.GetField("Events", BindingFlags.Instance|
BindingFlags.NonPublic);
MethodInfo methodGetItem = fieldEvents.FieldType.GetMethod("get_Item");
ItemCheckEventHandler tempCopy =
(ItemCheckEventHandler)methodGetItem.Invoke(fieldEvents.GetValue(this.contro
lX), new object[] {itemCheckID});

// Clear the delegate
MethodInfo methodSetItem = fieldEvents.FieldType.GetMethod("set_Item");
methodSetItem.Invoke(fieldEvents.GetValue(this.controlX), new object[]
{itemCheckID,null});

try
{
....
}
finally
{
// Restore the delegate
methodSetItem.Invoke(fieldEvents.GetValue(this.controlX), new
object[] {itemCheckID,tempCopy});
}
}


Thanks,
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no warranties, and confers no rights.
Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm





Serge Shimanovsky said:
Igor,

based on ILDasm RaiseItemCheck/add_itemCheck/remove_itemCheck (see the code
snippet in prev. reply), it takes Events[] from ComponentModel, so I don;t
believe they have internal array of delegates.

============================================================================
=================================

.method family hidebysig newslot virtual

instance void RaiseItemCheck(class
DevExpress.XtraEditors.Controls.ItemCheckEventArgs e) cil managed

{

// Code size 35 (0x23)

.maxstack 3

.locals init (class DevExpress.XtraEditors.Controls.ItemCheckEventHandler
V_0)

IL_0000: ldarg.0

IL_0001: call instance class [System]System.ComponentModel.EventHandlerList
[System]System.ComponentModel.Component::get_Events()

IL_0006: ldarg.0

IL_0007: ldfld object
DevExpress.XtraEditors.BaseCheckedListBoxControl::itemCheckID

IL_000c: callvirt instance class [mscorlib]System.Delegate
[System]System.ComponentModel.EventHandlerList::get_Item(object)

IL_0011: castclass DevExpress.XtraEditors.Controls.ItemCheckEventHandler

IL_0016: stloc.0

IL_0017: ldloc.0

IL_0018: brfalse.s IL_0022

IL_001a: ldloc.0

IL_001b: ldarg.0

IL_001c: ldarg.1

IL_001d: callvirt instance void
DevExpress.XtraEditors.Controls.ItemCheckEventHandler::Invoke(object,

class DevExpress.XtraEditors.Controls.ItemCheckEventArgs)

IL_0022: ret

} // end of method BaseCheckedListBoxControl::RaiseItemCheck



.method public hidebysig specialname instance void

add_ItemCheck(class DevExpress.XtraEditors.Controls.ItemCheckEventHandler
'value') cil managed

{

// Code size 19 (0x13)

.maxstack 3

IL_0000: ldarg.0

IL_0001: call instance class [System]System.ComponentModel.EventHandlerList
[System]System.ComponentModel.Component::get_Events()

IL_0006: ldarg.0

IL_0007: ldfld object
DevExpress.XtraEditors.BaseCheckedListBoxControl::itemCheckID

IL_000c: ldarg.1

IL_000d: callvirt instance void
[System]System.ComponentModel.EventHandlerList::AddHandler(object,

class [mscorlib]System.Delegate)

IL_0012: ret

} // end of method BaseCheckedListBoxControl::add_ItemCheck



.method public hidebysig specialname instance void

remove_ItemCheck(class DevExpress.XtraEditors.Controls.ItemCheckEventHandler
'value') cil managed

{

// Code size 19 (0x13)

.maxstack 3

IL_0000: ldarg.0

IL_0001: call instance class [System]System.ComponentModel.EventHandlerList
[System]System.ComponentModel.Component::get_Events()

IL_0006: ldarg.0

IL_0007: ldfld object
DevExpress.XtraEditors.BaseCheckedListBoxControl::itemCheckID

IL_000c: ldarg.1

IL_000d: callvirt instance void
[System]System.ComponentModel.EventHandlerList::RemoveHandler(object,

class [mscorlib]System.Delegate)

IL_0012: ret

} // end of method BaseCheckedListBoxControl::remove_ItemCheck



============================================================================
=================================

-Serge





Igor Zinkovsky said:
Serge,

The 1st condition "((1) ItemCheck event is defined in a way that caused the
compiler to define a private delegate with the same name)" was making an
assumption that the BaseControl class did not use accessors in defining
ItemCheck event. The assumption was relying on the compiler declaring a
private delegate with "ItemCheck" name. Since BaseControl does use
accessors for ItemCheck event - we can no longer assume that there is going
to be a private delegate with "ItemCheck" name.

Do you know any implementation details about the class for which you have
"Events" member in BaseControl?

Looking at the code you provided below, I am assuming that the class has an
internal data structure (array ?) that contains a list of delegate chains,
which are obtained through an indexer (based on itemCheckID). Without
knowing more about that data structure you can't reflect on the specific
ItemCheckEventHandler reference (that points to the delegate chain) in order
to temporarily set it to null.


Thanks,
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no warranties, and confers no rights.
Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm




Serge Shimanovsky said:
Igor,

I know. But this does not work either. Both of them return NULL.

They have declaration smth. like this:

--------------------------------------------------------------------------
--
--------------------
public abstract class BaseControl : BaseGrandparentControl
{
...
private readonly object itemCheckID = new object();

public event ItemCheckEventHandler ItemCheck {
add { Events.AddHandler(itemCheckID, value); }
remove { Events.RemoveHandler(itemCheckID, value); }
}
public delegate void ItemCheckEventHandler(object sender,
ItemCheckEventArgs e);

....

protected virtual void RaiseItemCheck(ItemCheckEventArgs e) {
ItemCheckEventHandler handler =
(ItemCheckEventHandler)Events[itemCheckID];
if(handler != null) handler(this, e);
}

}

public class controlX : BaseControl {

}


So, the
FieldInfo f =
this.controlX.GetType().BaseType.GetField("ItemCheck",
BindingFlags.Instance| BindingFlags.NonPublic);
or
FieldInfo f =
this.controlX.GetType().BaseType.GetField("ItemCheck",
BindingFlags.Instance| BindingFlags.Public);

return NULL. Any ideas?

-Serge

--------------------------------------------------------------------------
--
---------------------------
message Serge,

If I understand correctly, "ItemCheck" event is declared in some base
class,
and the class of controlX derives from that base class?

If this is correct - try using the "BaseType" property of the controlX's
type to get the type of the base class:

FieldInfo f = this.controlX.GetType().BaseType.GetField("ItemCheck",
BindingFlags.Instance| BindingFlags.NonPublic);

Thanks,
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no warranties, and confers no
rights.
Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm


Igor,

This is Ok as well as they have declaration of this handler in this
class,
but they do have this in the base class, so GetField() and .SetValue()
would
not work. Isn't it?

-Serge


"Igor Zinkovsky [MSFT]" <[email protected]>
wrote
in
message Serge, you can use the following, given that: (1) ItemCheck
event
is
defined
in a way that caused the compiler to define a private delegate with
the
same
name (2) Class where ItemCheck is declared allows modification of
private
members through reflection:

private void controlX_DataSourceChanged(object sender,
System.EventArgs
e)
{
FieldInfo f = this.controlX.GetType().GetField("ItemCheck",
BindingFlags.Instance| BindingFlags.NonPublic);
ItemCheckEventHandler tempCopy =
(ItemCheckEventHandler)f.GetValue(this.controlX);
f.SetValue(this.controlX, null);

try
{
....
}
finally
{
f.SetValue(this.controlX, tempCopy);
}
}


Thanks,
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no warranties, and confers no
rights.
Use of included script samples are subject to the terms
specified
at
http://www.microsoft.com/info/cpyright.htm


Igor,

Thank you very much. But the problem is that I'm using the
DevExpress
components and don't have access to their implementation. I
see
how
it
supoose to work, but lets say the situation I have right now. Is
there
any
other solution could be applied (I know the only way is to use
reflection,
but how?)

-Serge


in
message In your class (where ItemCheck is declared) you'll need to declare
a
private
delegate (to store listeners that sign up for ItemCheck event);
provide
add/remove accessors for ItemCheck event; and add extra
methods
to
save/restore the event:

class ...
{
private ItemCheckEventHandler _ItemCheck;
private ItemCheckEventHandler _SavedItemCheck;

public event ItemCheckEventHandler ItemCheck
{
add
{
_ItemCheck += new ItemCheckEventHandler(value);
}

remove
{
_ItemCheck -= new ItemCheckEventHandler(value);
}
}

// The method that fires the event needs to be changed to
trigger
the
private _ItemCheck
protected virtual void OnItemCheck()
{
ItemCheckEventHandler tempCopy = _ItemCheck;
if(tempCopy != null)
tempCopy(this, Args);
}

public void ClearItemCheck()
{
_SavedItemCheck = _ItemCheck;
_ItemCheck = null;
}

public void RestoreItemCheck()
{
_ItemCheck = _SavedItemCheck;
}
}


Hope this helps.
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no warranties, and confers
no
rights.
Use of included script samples are subject to the terms specified
at
http://www.microsoft.com/info/cpyright.htm



message
It would be nice, but doing this way I have the following error:

error CS0079: The
event
'DevExpress.XtraEditors.BaseCheckedListBoxControl.ItemCheck'
can only appear on the left hand side of += or -='

Any suggestions?

-Serge


"Igor Zinkovsky [MSFT]"
wrote
in
message Hi Serge.

If you want to temporarily clear ALL listeners that have
signed
up
for
your
ItemCheck event - you can use the way that you've provided
here
(1.
store
the delegate chain in a local variable, 2. set your ItemCheck
event
to
null, 3. do some work, 4. restore ItemCheck from your local
copy):

private void controlX_DataSourceChanged(object sender,
System.EventArgs
e)
{
ItemCheckEventHandler tempCopy = this.controlX.ItemCheck;
this.controlX.ItemCheck = null;

try
{
....
}
finally
{
this.controlX.ItemCheck = tempCopy;
}
}


In addition, you need to be careful if your app is
multithreaded.
This
is
to prevent situations when one thread has just removed all
event
listeners,
and another thread is trying to raise the event:

private void OnItemCheck()
{
ItemCheckEventHandler tempCopy = this.controlX.ItemCheck;
//
This
will create a new delegate chain since delegates are immutable
if(tempCopy != null)
tempCopy(this, Args);
}


Thanks,
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no warranties, and
confers
no
rights.
Use of included script samples are subject to the terms
specified
at
http://www.microsoft.com/info/cpyright.htm




message
Hi,


I have a situation where I need to clear the event sinks
from
an
event.
But
let's say I don't know which methods (by name, I mean)
signed
up
for
that
event.


I do have a control with lets say two events:
ItemCheck
and
DataSourceChange. Callbacks assigned to ItemCheck and
DataSourceChange
events at designtime.

The logic within DataSourceChanged callback requires
temporary
to
disable
the ItemCheck which can be accomplished by smth. Like this:

private void controlX_DataSourceChanged(object sender,
System.EventArgs
e)

{

this.controlX.ItemCheck -= new
ItemCheckEventHandler(this.controlX_ItemCheck);

try

{

....

}

finally

{

this.controlX.ItemCheck += new
ItemCheckEventHandler(this.controlX_ItemCheck);

}

}

Now, the question is how to do the same thing without
explicitly
specifying
this.controlX_ItemCheck name? I'm looking for
something
like
I
was
able
to
do in Delphi, for example,

1) store the existing one to the local variable

2) assign this one to null

3) do some work here...

4) restore back to the one stored into local variable

I believe you know what I'm talking about.



I know I have to use reflection in .NET/C# in order to get
this
thing
done,
but how?



P.S. Such things does not help because I have to
specify
the
name
of
the
callback explicitly as well:

// EventInfo ei = (sender as
MyControl).GetType().GetEvent("ItemCheck");

// Delegate d =
Delegate.CreateDelegate(ei.EventHandlerType,
this,
"controlX_ItemCheck");

ei.RemoveEventHandler(sender, d);

try

{

...

}

finally

{

ei.AddEventHandler(sender, d);

}



Thanks in advance,
Serge
 
S

Serge Shimanovsky

Igor,

Because "Events" declared :

protected System.ComponentModel.EventHandlerList Events [ get]
Member of System.ComponentModel.Component

the statement

FieldInfo fieldEvents = this.controlX.GetType().BaseType.GetField("Events",
BindingFlags.Instance | BindingFlags.NonPublic);

would return nothing. Right?

Even if I would dig down to the Component it would return nothing:

this.controlX.GetType().BaseType....BaseType.GetField("Events",
BindingFlags.Instance | BindingFlags.NonPublic);

I believe i have to specify binding flags to include
BindingFlags.GetProperty. But how would I get the MethodInfo from this to
save the delegate and to restore the delegate?

-Serge


Igor Zinkovsky said:
Serge,

It looks like Events is an instance of
System.ComponentModel.EventHandlerList.

The following should work for you:

private void controlX_DataSourceChanged(object sender,System.EventArgs e)
{
// Get the reference to BaseControl.itemCheckID
FieldInfo fieldItemCheckID =
this.controlX.GetType().BaseType.GetField("itemCheckID",
BindingFlags.Instance| BindingFlags.NonPublic);
object itemCheckID = FieldItemCheckID.GetValue(this.controlX);

// Save the delegate
FieldInfo fieldEvents =
this.controlX.GetType().BaseType.GetField("Events", BindingFlags.Instance|
BindingFlags.NonPublic);
MethodInfo methodGetItem = fieldEvents.FieldType.GetMethod("get_Item");
ItemCheckEventHandler tempCopy =
(ItemCheckEventHandler)methodGetItem.Invoke(fieldEvents.GetValue(this.contro
lX), new object[] {itemCheckID});

// Clear the delegate
MethodInfo methodSetItem = fieldEvents.FieldType.GetMethod("set_Item");
methodSetItem.Invoke(fieldEvents.GetValue(this.controlX), new object[]
{itemCheckID,null});

try
{
....
}
finally
{
// Restore the delegate
methodSetItem.Invoke(fieldEvents.GetValue(this.controlX), new
object[] {itemCheckID,tempCopy});
}
}


Thanks,
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no warranties, and confers no rights.
Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm





Serge Shimanovsky said:
Igor,

based on ILDasm RaiseItemCheck/add_itemCheck/remove_itemCheck (see the code
snippet in prev. reply), it takes Events[] from ComponentModel, so I don;t
believe they have internal array of delegates.
============================================================================
=================================

.method family hidebysig newslot virtual

instance void RaiseItemCheck(class
DevExpress.XtraEditors.Controls.ItemCheckEventArgs e) cil managed

{

// Code size 35 (0x23)

.maxstack 3

.locals init (class DevExpress.XtraEditors.Controls.ItemCheckEventHandler
V_0)

IL_0000: ldarg.0

IL_0001: call instance class [System]System.ComponentModel.EventHandlerList
[System]System.ComponentModel.Component::get_Events()

IL_0006: ldarg.0

IL_0007: ldfld object
DevExpress.XtraEditors.BaseCheckedListBoxControl::itemCheckID

IL_000c: callvirt instance class [mscorlib]System.Delegate
[System]System.ComponentModel.EventHandlerList::get_Item(object)

IL_0011: castclass DevExpress.XtraEditors.Controls.ItemCheckEventHandler

IL_0016: stloc.0

IL_0017: ldloc.0

IL_0018: brfalse.s IL_0022

IL_001a: ldloc.0

IL_001b: ldarg.0

IL_001c: ldarg.1

IL_001d: callvirt instance void
DevExpress.XtraEditors.Controls.ItemCheckEventHandler::Invoke(object,

class DevExpress.XtraEditors.Controls.ItemCheckEventArgs)

IL_0022: ret

} // end of method BaseCheckedListBoxControl::RaiseItemCheck



.method public hidebysig specialname instance void

add_ItemCheck(class DevExpress.XtraEditors.Controls.ItemCheckEventHandler
'value') cil managed

{

// Code size 19 (0x13)

.maxstack 3

IL_0000: ldarg.0

IL_0001: call instance class [System]System.ComponentModel.EventHandlerList
[System]System.ComponentModel.Component::get_Events()

IL_0006: ldarg.0

IL_0007: ldfld object
DevExpress.XtraEditors.BaseCheckedListBoxControl::itemCheckID

IL_000c: ldarg.1

IL_000d: callvirt instance void
[System]System.ComponentModel.EventHandlerList::AddHandler(object,

class [mscorlib]System.Delegate)

IL_0012: ret

} // end of method BaseCheckedListBoxControl::add_ItemCheck



.method public hidebysig specialname instance void

remove_ItemCheck(class DevExpress.XtraEditors.Controls.ItemCheckEventHandler
'value') cil managed

{

// Code size 19 (0x13)

.maxstack 3

IL_0000: ldarg.0

IL_0001: call instance class [System]System.ComponentModel.EventHandlerList
[System]System.ComponentModel.Component::get_Events()

IL_0006: ldarg.0

IL_0007: ldfld object
DevExpress.XtraEditors.BaseCheckedListBoxControl::itemCheckID

IL_000c: ldarg.1

IL_000d: callvirt instance void
[System]System.ComponentModel.EventHandlerList::RemoveHandler(object,

class [mscorlib]System.Delegate)

IL_0012: ret

} // end of method BaseCheckedListBoxControl::remove_ItemCheck
============================================================================
=================================

-Serge





Igor Zinkovsky said:
Serge,

The 1st condition "((1) ItemCheck event is defined in a way that
caused
the
compiler to define a private delegate with the same name)" was making an
assumption that the BaseControl class did not use accessors in defining
ItemCheck event. The assumption was relying on the compiler declaring a
private delegate with "ItemCheck" name. Since BaseControl does use
accessors for ItemCheck event - we can no longer assume that there is going
to be a private delegate with "ItemCheck" name.

Do you know any implementation details about the class for which you have
"Events" member in BaseControl?

Looking at the code you provided below, I am assuming that the class
has
an
internal data structure (array ?) that contains a list of delegate chains,
which are obtained through an indexer (based on itemCheckID). Without
knowing more about that data structure you can't reflect on the specific
ItemCheckEventHandler reference (that points to the delegate chain) in order
to temporarily set it to null.


Thanks,
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no warranties, and confers no rights.
Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm




Igor,

I know. But this does not work either. Both of them return NULL.

They have declaration smth. like this:

--------------------------------------------------------------------------
--
--------------------
public abstract class BaseControl : BaseGrandparentControl
{
...
private readonly object itemCheckID = new object();

public event ItemCheckEventHandler ItemCheck {
add { Events.AddHandler(itemCheckID, value); }
remove { Events.RemoveHandler(itemCheckID, value); }
}
public delegate void ItemCheckEventHandler(object sender,
ItemCheckEventArgs e);

....

protected virtual void RaiseItemCheck(ItemCheckEventArgs e) {
ItemCheckEventHandler handler =
(ItemCheckEventHandler)Events[itemCheckID];
if(handler != null) handler(this, e);
}

}

public class controlX : BaseControl {

}


So, the
FieldInfo f =
this.controlX.GetType().BaseType.GetField("ItemCheck",
BindingFlags.Instance| BindingFlags.NonPublic);
or
FieldInfo f =
this.controlX.GetType().BaseType.GetField("ItemCheck",
BindingFlags.Instance| BindingFlags.Public);

return NULL. Any ideas?

-Serge

--------------------------------------------------------------------------
--
---------------------------
message Serge,

If I understand correctly, "ItemCheck" event is declared in some base
class,
and the class of controlX derives from that base class?

If this is correct - try using the "BaseType" property of the controlX's
type to get the type of the base class:

FieldInfo f = this.controlX.GetType().BaseType.GetField("ItemCheck",
BindingFlags.Instance| BindingFlags.NonPublic);

Thanks,
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no warranties, and confers no
rights.
Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm


Igor,

This is Ok as well as they have declaration of this handler in this
class,
but they do have this in the base class, so GetField() and .SetValue()
would
not work. Isn't it?

-Serge


in
message Serge, you can use the following, given that: (1) ItemCheck
event
is
defined
in a way that caused the compiler to define a private delegate with
the
same
name (2) Class where ItemCheck is declared allows modification of
private
members through reflection:

private void controlX_DataSourceChanged(object sender,
System.EventArgs
e)
{
FieldInfo f = this.controlX.GetType().GetField("ItemCheck",
BindingFlags.Instance| BindingFlags.NonPublic);
ItemCheckEventHandler tempCopy =
(ItemCheckEventHandler)f.GetValue(this.controlX);
f.SetValue(this.controlX, null);

try
{
....
}
finally
{
f.SetValue(this.controlX, tempCopy);
}
}


Thanks,
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no warranties, and
confers
no
rights.
Use of included script samples are subject to the terms
specified
at
http://www.microsoft.com/info/cpyright.htm


Igor,

Thank you very much. But the problem is that I'm using the
DevExpress
components and don't have access to their implementation. I see
how
it
supoose to work, but lets say the situation I have right
now.
Is
there
any
other solution could be applied (I know the only way is to use
reflection,
but how?)

-Serge


"Igor Zinkovsky [MSFT]"
wrote
in
message In your class (where ItemCheck is declared) you'll need to
declare
a
private
delegate (to store listeners that sign up for ItemCheck event);
provide
add/remove accessors for ItemCheck event; and add extra methods
to
save/restore the event:

class ...
{
private ItemCheckEventHandler _ItemCheck;
private ItemCheckEventHandler _SavedItemCheck;

public event ItemCheckEventHandler ItemCheck
{
add
{
_ItemCheck += new ItemCheckEventHandler(value);
}

remove
{
_ItemCheck -= new ItemCheckEventHandler(value);
}
}

// The method that fires the event needs to be changed to
trigger
the
private _ItemCheck
protected virtual void OnItemCheck()
{
ItemCheckEventHandler tempCopy = _ItemCheck;
if(tempCopy != null)
tempCopy(this, Args);
}

public void ClearItemCheck()
{
_SavedItemCheck = _ItemCheck;
_ItemCheck = null;
}

public void RestoreItemCheck()
{
_ItemCheck = _SavedItemCheck;
}
}


Hope this helps.
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no warranties, and confers
no
rights.
Use of included script samples are subject to the terms
specified
at
http://www.microsoft.com/info/cpyright.htm



message
It would be nice, but doing this way I have the following
error:

error CS0079: The
event
'DevExpress.XtraEditors.BaseCheckedListBoxControl.ItemCheck'
can only appear on the left hand side of += or -='

Any suggestions?

-Serge


"Igor Zinkovsky [MSFT]"
wrote
in
message Hi Serge.

If you want to temporarily clear ALL listeners that have
signed
up
for
your
ItemCheck event - you can use the way that you've provided
here
(1.
store
the delegate chain in a local variable, 2. set your
ItemCheck
event
to
null, 3. do some work, 4. restore ItemCheck from your local
copy):

private void controlX_DataSourceChanged(object sender,
System.EventArgs
e)
{
ItemCheckEventHandler tempCopy =
this.controlX.ItemCheck;
this.controlX.ItemCheck = null;

try
{
....
}
finally
{
this.controlX.ItemCheck = tempCopy;
}
}


In addition, you need to be careful if your app is
multithreaded.
This
is
to prevent situations when one thread has just removed all
event
listeners,
and another thread is trying to raise the event:

private void OnItemCheck()
{
ItemCheckEventHandler tempCopy =
this.controlX.ItemCheck;
//
This
will create a new delegate chain since delegates are
immutable
if(tempCopy != null)
tempCopy(this, Args);
}


Thanks,
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no warranties, and
confers
no
rights.
Use of included script samples are subject to the terms
specified
at
http://www.microsoft.com/info/cpyright.htm




"Serge Shimanovsky" <[email protected]>
wrote
in
message
Hi,


I have a situation where I need to clear the event sinks
from
an
event.
But
let's say I don't know which methods (by name, I mean)
signed
up
for
that
event.


I do have a control with lets say two events: ItemCheck
and
DataSourceChange. Callbacks assigned to ItemCheck and
DataSourceChange
events at designtime.

The logic within DataSourceChanged callback requires
temporary
to
disable
the ItemCheck which can be accomplished by smth. Like
this:

private void controlX_DataSourceChanged(object sender,
System.EventArgs
e)

{

this.controlX.ItemCheck -= new
ItemCheckEventHandler(this.controlX_ItemCheck);

try

{

....

}

finally

{

this.controlX.ItemCheck += new
ItemCheckEventHandler(this.controlX_ItemCheck);

}

}

Now, the question is how to do the same thing without
explicitly
specifying
this.controlX_ItemCheck name? I'm looking for something
like
I
was
able
to
do in Delphi, for example,

1) store the existing one to the local variable

2) assign this one to null

3) do some work here...

4) restore back to the one stored into local variable

I believe you know what I'm talking about.



I know I have to use reflection in .NET/C# in order
to
get
this
thing
done,
but how?



P.S. Such things does not help because I have to specify
the
name
of
the
callback explicitly as well:

// EventInfo ei = (sender as
MyControl).GetType().GetEvent("ItemCheck");

// Delegate d =
Delegate.CreateDelegate(ei.EventHandlerType,
this,
"controlX_ItemCheck");

ei.RemoveEventHandler(sender, d);

try

{

...

}

finally

{

ei.AddEventHandler(sender, d);

}



Thanks in advance,
Serge
 
I

Igor Zinkovsky [MSFT]

Serge,

Since properties are really methods, you can do the following:

private void controlX_DataSourceChanged(object sender,System.EventArgs e)
{
// Get a reference to BaseControl.itemCheckID
FieldInfo fieldItemCheckID =
this.controlX.GetType().BaseType.GetField("itemCheckID",
BindingFlags.Instance| BindingFlags.NonPublic);
object itemCheckID = FieldItemCheckID.GetValue(this.controlX);

// Get a reference to EventHandlerList returned by Component.Events
MethodInfo methodGetEvents =
this.controlX.GetType().GetMethod("get_Events", BindingFlags.Instance|
BindingFlags.NonPublic);
EventHandlerList Events =
(EventHandlerList)methodGetEvents.Invoke(this.controlX, new object[] {});

// Save the delegate
ItemCheckEventHandler tempCopy =
(ItemCheckEventHandler)Events[itemCheckID];

// Clear the delegate
Events[itemCheckID] = null;

try
{
....
}
finally
{
// Restore the delegate
Events[itemCheckID] = tempCopy;
}
}



Thanks,
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no warranties, and confers no rights.
Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm






Serge Shimanovsky said:
Igor,

Because "Events" declared :

protected System.ComponentModel.EventHandlerList Events [ get]
Member of System.ComponentModel.Component

the statement

FieldInfo fieldEvents = this.controlX.GetType().BaseType.GetField("Events",
BindingFlags.Instance | BindingFlags.NonPublic);

would return nothing. Right?

Even if I would dig down to the Component it would return nothing:

this.controlX.GetType().BaseType....BaseType.GetField("Events",
BindingFlags.Instance | BindingFlags.NonPublic);

I believe i have to specify binding flags to include
BindingFlags.GetProperty. But how would I get the MethodInfo from this to
save the delegate and to restore the delegate?

-Serge


Igor Zinkovsky said:
Serge,

It looks like Events is an instance of
System.ComponentModel.EventHandlerList.

The following should work for you:

private void controlX_DataSourceChanged(object sender,System.EventArgs e)
{
// Get the reference to BaseControl.itemCheckID
FieldInfo fieldItemCheckID =
this.controlX.GetType().BaseType.GetField("itemCheckID",
BindingFlags.Instance| BindingFlags.NonPublic);
object itemCheckID = FieldItemCheckID.GetValue(this.controlX);

// Save the delegate
FieldInfo fieldEvents =
this.controlX.GetType().BaseType.GetField("Events", BindingFlags.Instance|
BindingFlags.NonPublic);
MethodInfo methodGetItem = fieldEvents.FieldType.GetMethod("get_Item");
ItemCheckEventHandler tempCopy =
(ItemCheckEventHandler)methodGetItem.Invoke(fieldEvents.GetValue(this.contro
lX), new object[] {itemCheckID});

// Clear the delegate
MethodInfo methodSetItem = fieldEvents.FieldType.GetMethod("set_Item");
methodSetItem.Invoke(fieldEvents.GetValue(this.controlX), new object[]
{itemCheckID,null});

try
{
....
}
finally
{
// Restore the delegate
methodSetItem.Invoke(fieldEvents.GetValue(this.controlX), new
object[] {itemCheckID,tempCopy});
}
}


Thanks,
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no warranties, and confers no rights.
Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm





Serge Shimanovsky said:
Igor,

based on ILDasm RaiseItemCheck/add_itemCheck/remove_itemCheck (see the code
snippet in prev. reply), it takes Events[] from ComponentModel, so I don;t
believe they have internal array of delegates.
============================================================================
=================================

.method family hidebysig newslot virtual

instance void RaiseItemCheck(class
DevExpress.XtraEditors.Controls.ItemCheckEventArgs e) cil managed

{

// Code size 35 (0x23)

.maxstack 3

.locals init (class DevExpress.XtraEditors.Controls.ItemCheckEventHandler
V_0)

IL_0000: ldarg.0

IL_0001: call instance class [System]System.ComponentModel.EventHandlerList
[System]System.ComponentModel.Component::get_Events()

IL_0006: ldarg.0

IL_0007: ldfld object
DevExpress.XtraEditors.BaseCheckedListBoxControl::itemCheckID

IL_000c: callvirt instance class [mscorlib]System.Delegate
[System]System.ComponentModel.EventHandlerList::get_Item(object)

IL_0011: castclass DevExpress.XtraEditors.Controls.ItemCheckEventHandler

IL_0016: stloc.0

IL_0017: ldloc.0

IL_0018: brfalse.s IL_0022

IL_001a: ldloc.0

IL_001b: ldarg.0

IL_001c: ldarg.1

IL_001d: callvirt instance void
DevExpress.XtraEditors.Controls.ItemCheckEventHandler::Invoke(object,

class DevExpress.XtraEditors.Controls.ItemCheckEventArgs)

IL_0022: ret

} // end of method BaseCheckedListBoxControl::RaiseItemCheck



.method public hidebysig specialname instance void

add_ItemCheck(class DevExpress.XtraEditors.Controls.ItemCheckEventHandler
'value') cil managed

{

// Code size 19 (0x13)

.maxstack 3

IL_0000: ldarg.0

IL_0001: call instance class [System]System.ComponentModel.EventHandlerList
[System]System.ComponentModel.Component::get_Events()

IL_0006: ldarg.0

IL_0007: ldfld object
DevExpress.XtraEditors.BaseCheckedListBoxControl::itemCheckID

IL_000c: ldarg.1

IL_000d: callvirt instance void
[System]System.ComponentModel.EventHandlerList::AddHandler(object,

class [mscorlib]System.Delegate)

IL_0012: ret

} // end of method BaseCheckedListBoxControl::add_ItemCheck



.method public hidebysig specialname instance void

remove_ItemCheck(class DevExpress.XtraEditors.Controls.ItemCheckEventHandler
'value') cil managed

{

// Code size 19 (0x13)

.maxstack 3

IL_0000: ldarg.0

IL_0001: call instance class [System]System.ComponentModel.EventHandlerList
[System]System.ComponentModel.Component::get_Events()

IL_0006: ldarg.0

IL_0007: ldfld object
DevExpress.XtraEditors.BaseCheckedListBoxControl::itemCheckID

IL_000c: ldarg.1

IL_000d: callvirt instance void
[System]System.ComponentModel.EventHandlerList::RemoveHandler(object,

class [mscorlib]System.Delegate)

IL_0012: ret

} // end of method BaseCheckedListBoxControl::remove_ItemCheck
============================================================================ making
declaring
a
private delegate with "ItemCheck" name. Since BaseControl does use
accessors for ItemCheck event - we can no longer assume that there is
going
to be a private delegate with "ItemCheck" name.

Do you know any implementation details about the class for which you have
"Events" member in BaseControl?

Looking at the code you provided below, I am assuming that the class has
an
internal data structure (array ?) that contains a list of delegate chains,
which are obtained through an indexer (based on itemCheckID). Without
knowing more about that data structure you can't reflect on the specific
ItemCheckEventHandler reference (that points to the delegate chain) in
order
to temporarily set it to null.


Thanks,
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no warranties, and confers no
rights.
Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm




Igor,

I know. But this does not work either. Both of them return NULL.

They have declaration smth. like this:

--------------------------------------------------------------------------
--
--------------------
public abstract class BaseControl : BaseGrandparentControl
{
...
private readonly object itemCheckID = new object();

public event ItemCheckEventHandler ItemCheck {
add { Events.AddHandler(itemCheckID, value); }
remove { Events.RemoveHandler(itemCheckID, value); }
}
public delegate void ItemCheckEventHandler(object sender,
ItemCheckEventArgs e);

....

protected virtual void RaiseItemCheck(ItemCheckEventArgs e) {
ItemCheckEventHandler handler =
(ItemCheckEventHandler)Events[itemCheckID];
if(handler != null) handler(this, e);
}

}

public class controlX : BaseControl {

}


So, the
FieldInfo f =
this.controlX.GetType().BaseType.GetField("ItemCheck",
BindingFlags.Instance| BindingFlags.NonPublic);
or
FieldInfo f =
this.controlX.GetType().BaseType.GetField("ItemCheck",
BindingFlags.Instance| BindingFlags.Public);

return NULL. Any ideas?

-Serge

-------------------------------------------------------------------------- wrote
in
message Serge,

If I understand correctly, "ItemCheck" event is declared in some base
class,
and the class of controlX derives from that base class?

If this is correct - try using the "BaseType" property of the
controlX's
type to get the type of the base class:

FieldInfo f = this.controlX.GetType().BaseType.GetField("ItemCheck",
BindingFlags.Instance| BindingFlags.NonPublic);

Thanks,
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no warranties, and confers no
rights.
Use of included script samples are subject to the terms
specified
at
http://www.microsoft.com/info/cpyright.htm


Igor,

This is Ok as well as they have declaration of this handler in this
class,
but they do have this in the base class, so GetField() and
.SetValue()
would
not work. Isn't it?

-Serge


in
message Serge, you can use the following, given that: (1) ItemCheck event
is
defined
in a way that caused the compiler to define a private delegate
with
the
same
name (2) Class where ItemCheck is declared allows
modification
of
private
members through reflection:

private void controlX_DataSourceChanged(object sender,
System.EventArgs
e)
{
FieldInfo f = this.controlX.GetType().GetField("ItemCheck",
BindingFlags.Instance| BindingFlags.NonPublic);
ItemCheckEventHandler tempCopy =
(ItemCheckEventHandler)f.GetValue(this.controlX);
f.SetValue(this.controlX, null);

try
{
....
}
finally
{
f.SetValue(this.controlX, tempCopy);
}
}


Thanks,
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no warranties, and confers
no
rights.
Use of included script samples are subject to the terms specified
at
http://www.microsoft.com/info/cpyright.htm


message
Igor,

Thank you very much. But the problem is that I'm using the
DevExpress
components and don't have access to their implementation.
I
see
how
it
supoose to work, but lets say the situation I have right
now.
Is
there
any
other solution could be applied (I know the only way is to use
reflection,
but how?)

-Serge


"Igor Zinkovsky [MSFT]"
wrote
in
message In your class (where ItemCheck is declared) you'll need to
declare
a
private
delegate (to store listeners that sign up for ItemCheck
event);
provide
add/remove accessors for ItemCheck event; and add extra
methods
to
save/restore the event:

class ...
{
private ItemCheckEventHandler _ItemCheck;
private ItemCheckEventHandler _SavedItemCheck;

public event ItemCheckEventHandler ItemCheck
{
add
{
_ItemCheck += new ItemCheckEventHandler(value);
}

remove
{
_ItemCheck -= new ItemCheckEventHandler(value);
}
}

// The method that fires the event needs to be
changed
to
trigger
the
private _ItemCheck
protected virtual void OnItemCheck()
{
ItemCheckEventHandler tempCopy = _ItemCheck;
if(tempCopy != null)
tempCopy(this, Args);
}

public void ClearItemCheck()
{
_SavedItemCheck = _ItemCheck;
_ItemCheck = null;
}

public void RestoreItemCheck()
{
_ItemCheck = _SavedItemCheck;
}
}


Hope this helps.
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no warranties, and
confers
no
rights.
Use of included script samples are subject to the terms
specified
at
http://www.microsoft.com/info/cpyright.htm



message
It would be nice, but doing this way I have the following
error:

error CS0079: The
event
'DevExpress.XtraEditors.BaseCheckedListBoxControl.ItemCheck'
can only appear on the left hand side of += or -='

Any suggestions?

-Serge


"Igor Zinkovsky [MSFT]"
<[email protected]>
wrote
in
message Hi Serge.

If you want to temporarily clear ALL listeners that have
signed
up
for
your
ItemCheck event - you can use the way that you've provided
here
(1.
store
the delegate chain in a local variable, 2. set your
ItemCheck
event
to
null, 3. do some work, 4. restore ItemCheck from your
local
copy):

private void controlX_DataSourceChanged(object sender,
System.EventArgs
e)
{
ItemCheckEventHandler tempCopy =
this.controlX.ItemCheck;
this.controlX.ItemCheck = null;

try
{
....
}
finally
{
this.controlX.ItemCheck = tempCopy;
}
}


In addition, you need to be careful if your app is
multithreaded.
This
is
to prevent situations when one thread has just
removed
all
event
listeners,
and another thread is trying to raise the event:

private void OnItemCheck()
{
ItemCheckEventHandler tempCopy =
this.controlX.ItemCheck;
//
This
will create a new delegate chain since delegates are
immutable
if(tempCopy != null)
tempCopy(this, Args);
}


Thanks,
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no warranties, and
confers
no
rights.
Use of included script samples are subject to the terms
specified
at
http://www.microsoft.com/info/cpyright.htm




in
message
Hi,


I have a situation where I need to clear the event sinks
from
an
event.
But
let's say I don't know which methods (by name, I mean)
signed
up
for
that
event.


I do have a control with lets say two events: ItemCheck
and
DataSourceChange. Callbacks assigned to ItemCheck and
DataSourceChange
events at designtime.

The logic within DataSourceChanged callback requires
temporary
to
disable
the ItemCheck which can be accomplished by smth. Like
this:

private void controlX_DataSourceChanged(object sender,
System.EventArgs
e)

{

this.controlX.ItemCheck -= new
ItemCheckEventHandler(this.controlX_ItemCheck);

try

{

....

}

finally

{

this.controlX.ItemCheck += new
ItemCheckEventHandler(this.controlX_ItemCheck);

}

}

Now, the question is how to do the same thing without
explicitly
specifying
this.controlX_ItemCheck name? I'm looking for something
like
I
was
able
to
do in Delphi, for example,

1) store the existing one to the local variable

2) assign this one to null

3) do some work here...

4) restore back to the one stored into local variable

I believe you know what I'm talking about.



I know I have to use reflection in .NET/C# in
order
 
S

Serge Shimanovsky

THANK YOU VERY MUCH, Igor!!!!!!!!
YOU ARE THE MAN!


Igor Zinkovsky said:
Serge,

Since properties are really methods, you can do the following:

private void controlX_DataSourceChanged(object sender,System.EventArgs e)
{
// Get a reference to BaseControl.itemCheckID
FieldInfo fieldItemCheckID =
this.controlX.GetType().BaseType.GetField("itemCheckID",
BindingFlags.Instance| BindingFlags.NonPublic);
object itemCheckID = FieldItemCheckID.GetValue(this.controlX);

// Get a reference to EventHandlerList returned by Component.Events
MethodInfo methodGetEvents =
this.controlX.GetType().GetMethod("get_Events", BindingFlags.Instance|
BindingFlags.NonPublic);
EventHandlerList Events =
(EventHandlerList)methodGetEvents.Invoke(this.controlX, new object[] {});

// Save the delegate
ItemCheckEventHandler tempCopy =
(ItemCheckEventHandler)Events[itemCheckID];

// Clear the delegate
Events[itemCheckID] = null;

try
{
....
}
finally
{
// Restore the delegate
Events[itemCheckID] = tempCopy;
}
}



Thanks,
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no warranties, and confers no rights.
Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm






Serge Shimanovsky said:
Igor,

Because "Events" declared :

protected System.ComponentModel.EventHandlerList Events [ get]
Member of System.ComponentModel.Component

the statement

FieldInfo fieldEvents = this.controlX.GetType().BaseType.GetField("Events",
BindingFlags.Instance | BindingFlags.NonPublic);

would return nothing. Right?

Even if I would dig down to the Component it would return nothing:

this.controlX.GetType().BaseType....BaseType.GetField("Events",
BindingFlags.Instance | BindingFlags.NonPublic);

I believe i have to specify binding flags to include
BindingFlags.GetProperty. But how would I get the MethodInfo from this to
save the delegate and to restore the delegate?

-Serge


Igor Zinkovsky said:
Serge,

It looks like Events is an instance of
System.ComponentModel.EventHandlerList.

The following should work for you:

private void controlX_DataSourceChanged(object sender,System.EventArgs e)
{
// Get the reference to BaseControl.itemCheckID
FieldInfo fieldItemCheckID =
this.controlX.GetType().BaseType.GetField("itemCheckID",
BindingFlags.Instance| BindingFlags.NonPublic);
object itemCheckID = FieldItemCheckID.GetValue(this.controlX);

// Save the delegate
FieldInfo fieldEvents =
this.controlX.GetType().BaseType.GetField("Events", BindingFlags.Instance|
BindingFlags.NonPublic);
MethodInfo methodGetItem = fieldEvents.FieldType.GetMethod("get_Item");
ItemCheckEventHandler tempCopy =
(ItemCheckEventHandler)methodGetItem.Invoke(fieldEvents.GetValue(this.contro
lX), new object[] {itemCheckID});

// Clear the delegate
MethodInfo methodSetItem = fieldEvents.FieldType.GetMethod("set_Item");
methodSetItem.Invoke(fieldEvents.GetValue(this.controlX), new object[]
{itemCheckID,null});

try
{
....
}
finally
{
// Restore the delegate
methodSetItem.Invoke(fieldEvents.GetValue(this.controlX), new
object[] {itemCheckID,tempCopy});
}
}


Thanks,
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no warranties, and confers no rights.
Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm





Igor,

based on ILDasm RaiseItemCheck/add_itemCheck/remove_itemCheck (see the
code
snippet in prev. reply), it takes Events[] from ComponentModel, so I don;t
believe they have internal array of delegates.
============================================================================
=================================

.method family hidebysig newslot virtual

instance void RaiseItemCheck(class
DevExpress.XtraEditors.Controls.ItemCheckEventArgs e) cil managed

{

// Code size 35 (0x23)

.maxstack 3

.locals init (class DevExpress.XtraEditors.Controls.ItemCheckEventHandler
V_0)

IL_0000: ldarg.0

IL_0001: call instance class
[System]System.ComponentModel.EventHandlerList
[System]System.ComponentModel.Component::get_Events()

IL_0006: ldarg.0

IL_0007: ldfld object
DevExpress.XtraEditors.BaseCheckedListBoxControl::itemCheckID

IL_000c: callvirt instance class [mscorlib]System.Delegate
[System]System.ComponentModel.EventHandlerList::get_Item(object)

IL_0011: castclass DevExpress.XtraEditors.Controls.ItemCheckEventHandler

IL_0016: stloc.0

IL_0017: ldloc.0

IL_0018: brfalse.s IL_0022

IL_001a: ldloc.0

IL_001b: ldarg.0

IL_001c: ldarg.1

IL_001d: callvirt instance void
DevExpress.XtraEditors.Controls.ItemCheckEventHandler::Invoke(object,

class DevExpress.XtraEditors.Controls.ItemCheckEventArgs)

IL_0022: ret

} // end of method BaseCheckedListBoxControl::RaiseItemCheck



.method public hidebysig specialname instance void

add_ItemCheck(class DevExpress.XtraEditors.Controls.ItemCheckEventHandler
'value') cil managed

{

// Code size 19 (0x13)

.maxstack 3

IL_0000: ldarg.0

IL_0001: call instance class
[System]System.ComponentModel.EventHandlerList
[System]System.ComponentModel.Component::get_Events()

IL_0006: ldarg.0

IL_0007: ldfld object
DevExpress.XtraEditors.BaseCheckedListBoxControl::itemCheckID

IL_000c: ldarg.1

IL_000d: callvirt instance void
[System]System.ComponentModel.EventHandlerList::AddHandler(object,

class [mscorlib]System.Delegate)

IL_0012: ret

} // end of method BaseCheckedListBoxControl::add_ItemCheck



.method public hidebysig specialname instance void

remove_ItemCheck(class
DevExpress.XtraEditors.Controls.ItemCheckEventHandler
'value') cil managed

{

// Code size 19 (0x13)

.maxstack 3

IL_0000: ldarg.0

IL_0001: call instance class
[System]System.ComponentModel.EventHandlerList
[System]System.ComponentModel.Component::get_Events()

IL_0006: ldarg.0

IL_0007: ldfld object
DevExpress.XtraEditors.BaseCheckedListBoxControl::itemCheckID

IL_000c: ldarg.1

IL_000d: callvirt instance void
[System]System.ComponentModel.EventHandlerList::RemoveHandler(object,

class [mscorlib]System.Delegate)

IL_0012: ret

} // end of method BaseCheckedListBoxControl::remove_ItemCheck
============================================================================
making declaring class
has
chain)
in
order
to temporarily set it to null.


Thanks,
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no warranties, and confers no
rights.
Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm




Igor,

I know. But this does not work either. Both of them return NULL.

They have declaration smth. like this:

--------------------------------------------------------------------------
--
--------------------
public abstract class BaseControl : BaseGrandparentControl
{
...
private readonly object itemCheckID = new object();

public event ItemCheckEventHandler ItemCheck {
add { Events.AddHandler(itemCheckID, value); }
remove { Events.RemoveHandler(itemCheckID, value); }
}
public delegate void ItemCheckEventHandler(object sender,
ItemCheckEventArgs e);

....

protected virtual void RaiseItemCheck(ItemCheckEventArgs e) {
ItemCheckEventHandler handler =
(ItemCheckEventHandler)Events[itemCheckID];
if(handler != null) handler(this, e);
}

}

public class controlX : BaseControl {

}


So, the
FieldInfo f =
this.controlX.GetType().BaseType.GetField("ItemCheck",
BindingFlags.Instance| BindingFlags.NonPublic);
or
FieldInfo f =
this.controlX.GetType().BaseType.GetField("ItemCheck",
BindingFlags.Instance| BindingFlags.Public);

return NULL. Any ideas?

-Serge

--------------------------------------------------------------------------
--
---------------------------
in
message Serge,

If I understand correctly, "ItemCheck" event is declared in some
base
class,
and the class of controlX derives from that base class?

If this is correct - try using the "BaseType" property of the
controlX's
type to get the type of the base class:

FieldInfo f = this.controlX.GetType().BaseType.GetField("ItemCheck",
BindingFlags.Instance| BindingFlags.NonPublic);

Thanks,
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no warranties, and
confers
no
rights.
Use of included script samples are subject to the terms
specified
at
http://www.microsoft.com/info/cpyright.htm


Igor,

This is Ok as well as they have declaration of this handler in
this
class,
but they do have this in the base class, so GetField() and
.SetValue()
would
not work. Isn't it?

-Serge


"Igor Zinkovsky [MSFT]"
wrote
in
message Serge, you can use the following, given that: (1) ItemCheck
event
is
defined
in a way that caused the compiler to define a private delegate
with
the
same
name (2) Class where ItemCheck is declared allows modification
of
private
members through reflection:

private void controlX_DataSourceChanged(object sender,
System.EventArgs
e)
{
FieldInfo f = this.controlX.GetType().GetField("ItemCheck",
BindingFlags.Instance| BindingFlags.NonPublic);
ItemCheckEventHandler tempCopy =
(ItemCheckEventHandler)f.GetValue(this.controlX);
f.SetValue(this.controlX, null);

try
{
....
}
finally
{
f.SetValue(this.controlX, tempCopy);
}
}


Thanks,
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no warranties, and confers
no
rights.
Use of included script samples are subject to the terms
specified
at
http://www.microsoft.com/info/cpyright.htm


message
Igor,

Thank you very much. But the problem is that I'm using the
DevExpress
components and don't have access to their
implementation.
I
see
how
it
supoose to work, but lets say the situation I have right now.
Is
there
any
other solution could be applied (I know the only way is
to
use
reflection,
but how?)

-Serge


"Igor Zinkovsky [MSFT]"
wrote
in
message In your class (where ItemCheck is declared) you'll
need
to
declare
a
private
delegate (to store listeners that sign up for ItemCheck
event);
provide
add/remove accessors for ItemCheck event; and add extra
methods
to
save/restore the event:

class ...
{
private ItemCheckEventHandler _ItemCheck;
private ItemCheckEventHandler _SavedItemCheck;

public event ItemCheckEventHandler ItemCheck
{
add
{
_ItemCheck += new ItemCheckEventHandler(value);
}

remove
{
_ItemCheck -= new ItemCheckEventHandler(value);
}
}

// The method that fires the event needs to be changed
to
trigger
the
private _ItemCheck
protected virtual void OnItemCheck()
{
ItemCheckEventHandler tempCopy = _ItemCheck;
if(tempCopy != null)
tempCopy(this, Args);
}

public void ClearItemCheck()
{
_SavedItemCheck = _ItemCheck;
_ItemCheck = null;
}

public void RestoreItemCheck()
{
_ItemCheck = _SavedItemCheck;
}
}


Hope this helps.
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no warranties, and
confers
no
rights.
Use of included script samples are subject to the terms
specified
at
http://www.microsoft.com/info/cpyright.htm



"Serge Shimanovsky" <[email protected]>
wrote
in
message
It would be nice, but doing this way I have the following
error:

error CS0079: The
event
'DevExpress.XtraEditors.BaseCheckedListBoxControl.ItemCheck'
can only appear on the left hand side of += or -='

Any suggestions?

-Serge


"Igor Zinkovsky [MSFT]"
<[email protected]>
wrote
in
message Hi Serge.

If you want to temporarily clear ALL listeners
that
have
signed
up
for
your
ItemCheck event - you can use the way that you've
provided
here
(1.
store
the delegate chain in a local variable, 2. set your
ItemCheck
event
to
null, 3. do some work, 4. restore ItemCheck from your
local
copy):

private void controlX_DataSourceChanged(object sender,
System.EventArgs
e)
{
ItemCheckEventHandler tempCopy =
this.controlX.ItemCheck;
this.controlX.ItemCheck = null;

try
{
....
}
finally
{
this.controlX.ItemCheck = tempCopy;
}
}


In addition, you need to be careful if your app is
multithreaded.
This
is
to prevent situations when one thread has just removed
all
event
listeners,
and another thread is trying to raise the event:

private void OnItemCheck()
{
ItemCheckEventHandler tempCopy =
this.controlX.ItemCheck;
//
This
will create a new delegate chain since delegates are
immutable
if(tempCopy != null)
tempCopy(this, Args);
}


Thanks,
Igor Zinkovsky [MSFT]
Visual Studio Build/Release Team

This posting is provided "AS IS" with no
warranties,
and
confers
no
rights.
Use of included script samples are subject to the terms
specified
at
http://www.microsoft.com/info/cpyright.htm




in
message
Hi,


I have a situation where I need to clear the event
sinks
from
an
event.
But
let's say I don't know which methods (by name, I mean)
signed
up
for
that
event.


I do have a control with lets say two events:
ItemCheck
and
DataSourceChange. Callbacks assigned to
ItemCheck
and
DataSourceChange
events at designtime.

The logic within DataSourceChanged callback requires
temporary
to
disable
the ItemCheck which can be accomplished by smth. Like
this:

private void controlX_DataSourceChanged(object sender,
System.EventArgs
e)

{

this.controlX.ItemCheck -= new
ItemCheckEventHandler(this.controlX_ItemCheck);

try

{

....

}

finally

{

this.controlX.ItemCheck += new
ItemCheckEventHandler(this.controlX_ItemCheck);

}

}

Now, the question is how to do the same thing without
explicitly
specifying
this.controlX_ItemCheck name? I'm looking for
something
like
I
was
able
to
do in Delphi, for example,

1) store the existing one to the local variable

2) assign this one to null

3) do some work here...

4) restore back to the one stored into local variable

I believe you know what I'm talking about.



I know I have to use reflection in .NET/C# in
order
to
get
this
thing
done,
but how?



P.S. Such things does not help because I have to
specify
the
name
of
the
callback explicitly as well:

// EventInfo ei = (sender as
MyControl).GetType().GetEvent("ItemCheck");

// Delegate d =
Delegate.CreateDelegate(ei.EventHandlerType,
this,
"controlX_ItemCheck");

ei.RemoveEventHandler(sender, d);

try

{

...

}

finally

{

ei.AddEventHandler(sender, d);

}



Thanks in advance,
Serge
 
Top