0

I have an object that has events. I want to reset that object to default but keep the existing event subscriptions. My aim is to have a bunch of subscriptions to events on this object (_myRepo), then at some point I want to set _myRepo = null, create a new copy of the object with it's default state and then add back all the previously save subscribers. I use a generic approach instead of strong typing due to their being many repos in this class.

The issue I'm having is trying to add the subscription back to the event once it's has been recreated. I'm trying to do this in the ApplyCachedEventHandlers() function. How do I add this delegate back to the new object's event?

This is what I'm doing so far...

private IMyRepo _myRepo;
private Dictionary<Type, Delegate> _subscribers = new Dictionary<Type, Delegate>();

public IMyRepo MyRepo
{
    get
    {
        if (_myRepo == null)
            _myRepo = new MyRepo(_transaction);
        ApplyCachedEventHandlers(_myRepo);

        return _myRepo;
    }
}

private void ResetRepo()
{
    CacheEventHandlers(_myRepo);
    _myRepo = null;
}

private void CacheEventHandlers<T>(T repo)
{
    if (repo == null)
        return;

    Type t = repo.GetType();
    FieldInfo[] fia = t.GetFields(BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic);

    foreach (FieldInfo fi in fia)
    {
        Delegate d = fi.GetValue(repo) as Delegate;
        if (d != null)
        {
            foreach (Delegate subscriber in d.GetInvocationList())
                _subscribers.Add(t, subscriber);
        }
    }
}

private void ApplyCachedEventHandlers<T>(T repo)
{
    if (repo == null || _subscribers == null || _subscribers.Count < 1)
        return;

    Type t = repo.GetType();
    FieldInfo[] fia = t.GetFields(BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic);

    foreach (KeyValuePair<Type, Delegate> subscriber in _subscribers)
    {
        if (t == subscriber.Key)
        {
            foreach (FieldInfo fi in fia)
            {
                // This is where I get hung up
                Debug.WriteLine("Add the saved delegate to the subscriptions of the event (fi).");
            }
        }
    }
}
Arvo Bowen
  • 4,524
  • 6
  • 51
  • 109
  • Can you please add a [mre] which can be compiled and run? – Guru Stron May 17 '23 at 18:42
  • @GuruStron it's quite a lot of code to compile. I tried to just include a simple version of the key components revolving around my class. Is there a specific question you had that I should be able to answer for you? I have made my objectives clear in the question. I just need to know how to add an existing `Delegate` to a `FieldInfo` object. Sorry if my terminology is a little wrong. – Arvo Bowen May 17 '23 at 19:05

1 Answers1

0

If you want to subscribe to event via reflection you should not work with fields, but with events:

var eventInfos = type.GetEvents(); // pass the flags if needed
foreach (KeyValuePair<Type, Delegate> subscriber in _subscribers)
{
    if (t == subscriber.Key)
    {
        foreach (EventInfo ei in eventInfos)
        {
            ei.AddEventHandler(repo, subscriber.Value); 
        }
    }
}
Arvo Bowen
  • 4,524
  • 6
  • 51
  • 109
Guru Stron
  • 102,774
  • 10
  • 95
  • 132
  • 1
    Thanks man! I think this is exactly what I needed. Sometimes it's just about knowing what the correct thing to search for. – Arvo Bowen May 17 '23 at 19:36