Unsubscribing from, or checking for, the CollectionChanged event via reflection
I have used reflection in my project to add events to ObservableCollections
- specifically, CollectionChanged
. I am able to add the event well enough and there is no problem there. The problem is that the code to add the event is run more than once and so I end up with multiple identical events added in some cases. What I don't know how to do is either check to see if there is already an event assigned, or to remove before I add one (to ensure there is only one event added).
The code is here:
foreach (PropertyInfo propertyInfo in props)
{
nType = this.GetPropertyInfoTypeObs(propertyInfo.PropertyType);
if (nType == Static_Enums.TypeEnums.TYPE_OBSERVABLE_COLLECTION)
{
var genargs = propertyInfo.PropertyType.GetGenericArguments();
var o = propertyInfo.GetValue(this, null);
EventInfo evi = o.GetType().GetEvent("CollectionChanged", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
var eventHandler = new Action<object, NotifyCollectionChangedEventArgs>(
(s, a) =>
{
// Event code here
this.MakePropertyDirty(propertyInfo.Name);
});
var del = Delegate.CreateDelegate(evi.EventHandlerType, eventHandler.Target, eventHandler.Method);
evi.AddEventHandler(o, del);
}
}
As stated, this part works fine. But how to handle the issue of the event being added more than once?
I first tried simply having evi.RemoveEventHandler(o, del)
on the line above. This doesn't work for me - as in, if I watch what happens when that line is executed, the event handler seems to remain untouched. Perhaps I'm doing it incorrectly?
I'd also be happy with a way to check if the event handler already has one assigned, and then skip over adding it again. But how to do that I've no idea.
Edit
I have tried creating the delegate as a class property in order that it can persist. But even still, as I trace over the lines, I can see that the handler is not removed when I call the evi.RemoveEventHandler
with this property delegate.
I then went a little further and tried doing this:
EventInfo ef = o.GetType().GetEvent("CollectionChanged");
MethodInfo rem = ef.GetRemoveMethod();
ParameterInfo piList = rem.GetParameters();
object oList = new object[1];
oList[0] = storedProc;
rem.Invoke(o, oList);
Unfortunately it also doesn't seem to do the trick.
Furthermore, I read that in order to remove a handler, it has to be the exact same handler in the remove method. Now, in this method here, the derived class has more than one ObservableCollection
. So I tried limiting the creation of the new delegate (and assigning it to the class property) to only in the case of a particularly named ObservableCollection
(one I knew would appear). I traced it over again, one line at a time, and the event handler was not removed.
Even if this did work, however, I'd then have to store a delegate for each ObservableCollection
for which I did this. My god, can't I just tell it to clear the event?
c# events reflection observablecollection
add a comment |
I have used reflection in my project to add events to ObservableCollections
- specifically, CollectionChanged
. I am able to add the event well enough and there is no problem there. The problem is that the code to add the event is run more than once and so I end up with multiple identical events added in some cases. What I don't know how to do is either check to see if there is already an event assigned, or to remove before I add one (to ensure there is only one event added).
The code is here:
foreach (PropertyInfo propertyInfo in props)
{
nType = this.GetPropertyInfoTypeObs(propertyInfo.PropertyType);
if (nType == Static_Enums.TypeEnums.TYPE_OBSERVABLE_COLLECTION)
{
var genargs = propertyInfo.PropertyType.GetGenericArguments();
var o = propertyInfo.GetValue(this, null);
EventInfo evi = o.GetType().GetEvent("CollectionChanged", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
var eventHandler = new Action<object, NotifyCollectionChangedEventArgs>(
(s, a) =>
{
// Event code here
this.MakePropertyDirty(propertyInfo.Name);
});
var del = Delegate.CreateDelegate(evi.EventHandlerType, eventHandler.Target, eventHandler.Method);
evi.AddEventHandler(o, del);
}
}
As stated, this part works fine. But how to handle the issue of the event being added more than once?
I first tried simply having evi.RemoveEventHandler(o, del)
on the line above. This doesn't work for me - as in, if I watch what happens when that line is executed, the event handler seems to remain untouched. Perhaps I'm doing it incorrectly?
I'd also be happy with a way to check if the event handler already has one assigned, and then skip over adding it again. But how to do that I've no idea.
Edit
I have tried creating the delegate as a class property in order that it can persist. But even still, as I trace over the lines, I can see that the handler is not removed when I call the evi.RemoveEventHandler
with this property delegate.
I then went a little further and tried doing this:
EventInfo ef = o.GetType().GetEvent("CollectionChanged");
MethodInfo rem = ef.GetRemoveMethod();
ParameterInfo piList = rem.GetParameters();
object oList = new object[1];
oList[0] = storedProc;
rem.Invoke(o, oList);
Unfortunately it also doesn't seem to do the trick.
Furthermore, I read that in order to remove a handler, it has to be the exact same handler in the remove method. Now, in this method here, the derived class has more than one ObservableCollection
. So I tried limiting the creation of the new delegate (and assigning it to the class property) to only in the case of a particularly named ObservableCollection
(one I knew would appear). I traced it over again, one line at a time, and the event handler was not removed.
Even if this did work, however, I'd then have to store a delegate for each ObservableCollection
for which I did this. My god, can't I just tell it to clear the event?
c# events reflection observablecollection
You have to preserve the delegate you got fromDelegate.CreateDelegate
somewhere. Then you can check later if this paticular delegate instance is already subscribed.
– thehennyy
Nov 25 '18 at 11:24
I can see the code to remove a delegate, using 'RemoveEventHandler', but I didn't see an obvious way to check whether it was already subscribed. Did I miss something in EventInfo?
– TheFaithfulLearner
Nov 25 '18 at 15:25
You can probably get the invocation list of the underlaying delegate that represents the event. But thats certainly implementation-dependant, like the backing field of properties.
– thehennyy
Nov 26 '18 at 6:32
add a comment |
I have used reflection in my project to add events to ObservableCollections
- specifically, CollectionChanged
. I am able to add the event well enough and there is no problem there. The problem is that the code to add the event is run more than once and so I end up with multiple identical events added in some cases. What I don't know how to do is either check to see if there is already an event assigned, or to remove before I add one (to ensure there is only one event added).
The code is here:
foreach (PropertyInfo propertyInfo in props)
{
nType = this.GetPropertyInfoTypeObs(propertyInfo.PropertyType);
if (nType == Static_Enums.TypeEnums.TYPE_OBSERVABLE_COLLECTION)
{
var genargs = propertyInfo.PropertyType.GetGenericArguments();
var o = propertyInfo.GetValue(this, null);
EventInfo evi = o.GetType().GetEvent("CollectionChanged", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
var eventHandler = new Action<object, NotifyCollectionChangedEventArgs>(
(s, a) =>
{
// Event code here
this.MakePropertyDirty(propertyInfo.Name);
});
var del = Delegate.CreateDelegate(evi.EventHandlerType, eventHandler.Target, eventHandler.Method);
evi.AddEventHandler(o, del);
}
}
As stated, this part works fine. But how to handle the issue of the event being added more than once?
I first tried simply having evi.RemoveEventHandler(o, del)
on the line above. This doesn't work for me - as in, if I watch what happens when that line is executed, the event handler seems to remain untouched. Perhaps I'm doing it incorrectly?
I'd also be happy with a way to check if the event handler already has one assigned, and then skip over adding it again. But how to do that I've no idea.
Edit
I have tried creating the delegate as a class property in order that it can persist. But even still, as I trace over the lines, I can see that the handler is not removed when I call the evi.RemoveEventHandler
with this property delegate.
I then went a little further and tried doing this:
EventInfo ef = o.GetType().GetEvent("CollectionChanged");
MethodInfo rem = ef.GetRemoveMethod();
ParameterInfo piList = rem.GetParameters();
object oList = new object[1];
oList[0] = storedProc;
rem.Invoke(o, oList);
Unfortunately it also doesn't seem to do the trick.
Furthermore, I read that in order to remove a handler, it has to be the exact same handler in the remove method. Now, in this method here, the derived class has more than one ObservableCollection
. So I tried limiting the creation of the new delegate (and assigning it to the class property) to only in the case of a particularly named ObservableCollection
(one I knew would appear). I traced it over again, one line at a time, and the event handler was not removed.
Even if this did work, however, I'd then have to store a delegate for each ObservableCollection
for which I did this. My god, can't I just tell it to clear the event?
c# events reflection observablecollection
I have used reflection in my project to add events to ObservableCollections
- specifically, CollectionChanged
. I am able to add the event well enough and there is no problem there. The problem is that the code to add the event is run more than once and so I end up with multiple identical events added in some cases. What I don't know how to do is either check to see if there is already an event assigned, or to remove before I add one (to ensure there is only one event added).
The code is here:
foreach (PropertyInfo propertyInfo in props)
{
nType = this.GetPropertyInfoTypeObs(propertyInfo.PropertyType);
if (nType == Static_Enums.TypeEnums.TYPE_OBSERVABLE_COLLECTION)
{
var genargs = propertyInfo.PropertyType.GetGenericArguments();
var o = propertyInfo.GetValue(this, null);
EventInfo evi = o.GetType().GetEvent("CollectionChanged", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
var eventHandler = new Action<object, NotifyCollectionChangedEventArgs>(
(s, a) =>
{
// Event code here
this.MakePropertyDirty(propertyInfo.Name);
});
var del = Delegate.CreateDelegate(evi.EventHandlerType, eventHandler.Target, eventHandler.Method);
evi.AddEventHandler(o, del);
}
}
As stated, this part works fine. But how to handle the issue of the event being added more than once?
I first tried simply having evi.RemoveEventHandler(o, del)
on the line above. This doesn't work for me - as in, if I watch what happens when that line is executed, the event handler seems to remain untouched. Perhaps I'm doing it incorrectly?
I'd also be happy with a way to check if the event handler already has one assigned, and then skip over adding it again. But how to do that I've no idea.
Edit
I have tried creating the delegate as a class property in order that it can persist. But even still, as I trace over the lines, I can see that the handler is not removed when I call the evi.RemoveEventHandler
with this property delegate.
I then went a little further and tried doing this:
EventInfo ef = o.GetType().GetEvent("CollectionChanged");
MethodInfo rem = ef.GetRemoveMethod();
ParameterInfo piList = rem.GetParameters();
object oList = new object[1];
oList[0] = storedProc;
rem.Invoke(o, oList);
Unfortunately it also doesn't seem to do the trick.
Furthermore, I read that in order to remove a handler, it has to be the exact same handler in the remove method. Now, in this method here, the derived class has more than one ObservableCollection
. So I tried limiting the creation of the new delegate (and assigning it to the class property) to only in the case of a particularly named ObservableCollection
(one I knew would appear). I traced it over again, one line at a time, and the event handler was not removed.
Even if this did work, however, I'd then have to store a delegate for each ObservableCollection
for which I did this. My god, can't I just tell it to clear the event?
c# events reflection observablecollection
c# events reflection observablecollection
edited Nov 25 '18 at 20:33
TheFaithfulLearner
asked Nov 25 '18 at 11:16
TheFaithfulLearnerTheFaithfulLearner
196113
196113
You have to preserve the delegate you got fromDelegate.CreateDelegate
somewhere. Then you can check later if this paticular delegate instance is already subscribed.
– thehennyy
Nov 25 '18 at 11:24
I can see the code to remove a delegate, using 'RemoveEventHandler', but I didn't see an obvious way to check whether it was already subscribed. Did I miss something in EventInfo?
– TheFaithfulLearner
Nov 25 '18 at 15:25
You can probably get the invocation list of the underlaying delegate that represents the event. But thats certainly implementation-dependant, like the backing field of properties.
– thehennyy
Nov 26 '18 at 6:32
add a comment |
You have to preserve the delegate you got fromDelegate.CreateDelegate
somewhere. Then you can check later if this paticular delegate instance is already subscribed.
– thehennyy
Nov 25 '18 at 11:24
I can see the code to remove a delegate, using 'RemoveEventHandler', but I didn't see an obvious way to check whether it was already subscribed. Did I miss something in EventInfo?
– TheFaithfulLearner
Nov 25 '18 at 15:25
You can probably get the invocation list of the underlaying delegate that represents the event. But thats certainly implementation-dependant, like the backing field of properties.
– thehennyy
Nov 26 '18 at 6:32
You have to preserve the delegate you got from
Delegate.CreateDelegate
somewhere. Then you can check later if this paticular delegate instance is already subscribed.– thehennyy
Nov 25 '18 at 11:24
You have to preserve the delegate you got from
Delegate.CreateDelegate
somewhere. Then you can check later if this paticular delegate instance is already subscribed.– thehennyy
Nov 25 '18 at 11:24
I can see the code to remove a delegate, using 'RemoveEventHandler', but I didn't see an obvious way to check whether it was already subscribed. Did I miss something in EventInfo?
– TheFaithfulLearner
Nov 25 '18 at 15:25
I can see the code to remove a delegate, using 'RemoveEventHandler', but I didn't see an obvious way to check whether it was already subscribed. Did I miss something in EventInfo?
– TheFaithfulLearner
Nov 25 '18 at 15:25
You can probably get the invocation list of the underlaying delegate that represents the event. But thats certainly implementation-dependant, like the backing field of properties.
– thehennyy
Nov 26 '18 at 6:32
You can probably get the invocation list of the underlaying delegate that represents the event. But thats certainly implementation-dependant, like the backing field of properties.
– thehennyy
Nov 26 '18 at 6:32
add a comment |
0
active
oldest
votes
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53466907%2funsubscribing-from-or-checking-for-the-collectionchanged-event-via-reflection%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
0
active
oldest
votes
0
active
oldest
votes
active
oldest
votes
active
oldest
votes
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53466907%2funsubscribing-from-or-checking-for-the-collectionchanged-event-via-reflection%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
You have to preserve the delegate you got from
Delegate.CreateDelegate
somewhere. Then you can check later if this paticular delegate instance is already subscribed.– thehennyy
Nov 25 '18 at 11:24
I can see the code to remove a delegate, using 'RemoveEventHandler', but I didn't see an obvious way to check whether it was already subscribed. Did I miss something in EventInfo?
– TheFaithfulLearner
Nov 25 '18 at 15:25
You can probably get the invocation list of the underlaying delegate that represents the event. But thats certainly implementation-dependant, like the backing field of properties.
– thehennyy
Nov 26 '18 at 6:32