Unsubscribing from, or checking for, the CollectionChanged event via reflection












0















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?










share|improve this question

























  • 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
















0















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?










share|improve this question

























  • 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














0












0








0








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?










share|improve this question
















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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








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 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



















  • 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

















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












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
});


}
});














draft saved

draft discarded


















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
















draft saved

draft discarded




















































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.




draft saved


draft discarded














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





















































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







Popular posts from this blog

Wiesbaden

Marschland

Dieringhausen