20

We need to get all the instances of objects that implement a given interface - can we do that, and if so how?

Simon
  • 25,468
  • 44
  • 152
  • 266

5 Answers5

20

If you need instances (samples) of all types implementing particular interface you can go through all types, check for interface and create instance if match found.

Here's some pseudocode that looks remarkably like C# and may even compile and return what you need. If nothing else, it will point you in the correct direction:

public static IEnumerable<T> GetInstancesOfImplementingTypes<T>()
{
    AppDomain app = AppDomain.CurrentDomain;
    Assembly[] ass = app.GetAssemblies();
    Type[] types;
    Type targetType = typeof(T);

    foreach (Assembly a in ass)
    {
        types = a.GetTypes();
        foreach (Type t in types)
        {
            if (t.IsInterface) continue;
            if (t.IsAbstract) continue;
            foreach (Type iface in t.GetInterfaces())
            {
                if (!iface.Equals(targetType)) continue;
                yield return (T) Activator.CreateInstance(t);
                break;
            }
        }
    }
}

Now, if you're talking about walking the heap and returning previously instantiated instances of all objects that implement a particular type, good luck on that as this information is not stored by .Net runtime (can be computed by debugers/profilers by examining heap/stack so).

Depending on the reason why you think you need to do that there are probably better ways of going about it.

Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179
  • 2
    Yeah, I want to get previously-instantiated instances. It's because we load modules that store their settings using objects that implement the same interface, but there doesn't seem to be any other way to get the setting instances out. – Simon Nov 19 '08 at 17:29
  • +1 thanks. Added the cast to T which made the code compile for me. – Sam Holder Jun 07 '11 at 09:46
  • 1
    This will fail for types that aren't exportable to the calling assembly, but there is a fix for that, if you look... –  Oct 26 '12 at 18:33
  • 2
    This is enumerating through all types defined in your referenced assemblies, not all instances of those types. – Charles Bretana Jun 11 '15 at 18:44
  • 1
    @CharlesBretana Well, thanks for the heads up on this almost-nine-year-old answer! I'll direct you to the [original question as it was posted and answered](http://stackoverflow.com/revisions/302542/1). You will note that OP is unclear in what he was asking. I took a stab and at least a few people agreed with me. Please note that this was back in the day when SO didn't have comments nor the ability to provide feedback through specific closure reasons. I'd also like to invite you to go be pedantic elsewhere. Thanks for your participation! –  Jun 11 '15 at 19:18
  • @Will - I've edited your post as this was used as duplicate target of http://stackoverflow.com/questions/40615126/how-to-get-a-reference-to-all-instances-in-a-c-sharp-application and potentially one could guess that code actually gives "all existing instances"... Feel free to rollback if you find it not matching your intentions. – Alexei Levenkov Nov 15 '16 at 16:58
9

I don't believe there is a way... You would have to either be able to walk the Heap, and examine every object there, or walk the stack of every active thread in the application process space, examining every stack reference variable on every thread...

The other way, (I am guessing you can't do) is intercept all Object creation activities (using a container approach) and keep a list of all objects in your application...

Charles Bretana
  • 143,358
  • 22
  • 150
  • 216
  • I asked essentially the same question in [c# - Enumerate all instances of a class](https://stackoverflow.com/questions/52264417/enumerate-all-instances-of-a-class?noredirect=1#comment91520290_52264417). Can Profiling (as in [Profiling Overview](https://learn.microsoft.com/en-us/dotnet/framework/unmanaged-api/profiling/profiling-overview#profiling_api)) be used? What about [CodeInject](https://github.com/punitganshani/codeinject) or [dI.Hook](https://github.com/punitganshani/dI.Hook)? – Sam Hobbs Sep 13 '18 at 17:46
4

All instances of an Object, or all Types?

Getting all instances of an Object would be pretty close to impossible, and would involve non-public information about the scan through management memory.

Getting all types that implement a given interface is doable --- within a given domain. (ie, you can find all type defined within an assembly that implement a particular interface)

  • Load the Assembly
  • Iterate through it's types (call asm.GetTypes())
  • Check typeof(IMyInterface).IsAssignibleFrom(testType)
James Curran
  • 101,701
  • 37
  • 181
  • 258
2

If the classes implementing the specified interface are yours then you can implement a list of weak references upon instantiation.

1
IEnumerable<Type> GetAllTypesThatImplementInterface<T>()
{
    var @interface = typeof (T);
    return @interface.IsInterface
               ? AppDomain.CurrentDomain.GetAssemblies()
                     .SelectMany(assembly => assembly.GetTypes())
                     .Where(type => !type.IsInterface
                                 && !type.IsAbstract 
                                 && type.GetInterfaces().Contains(@interface))
               : new Type[] {};
}
agentnega
  • 3,478
  • 1
  • 25
  • 31
smartcaveman
  • 41,281
  • 29
  • 127
  • 212
  • 1
    nice - but how do I get the instances of those types? – Simon Jun 07 '11 at 15:00
  • 1
    @Simon, The only way to do this is to register references to each instance on creation. You can't access them without establishing such a mechanism upfront. Depending on your use case, you might want to look into [ObservableCollection](http://msdn.microsoft.com/en-us/library/ms668604.aspx)... What is your use case? – smartcaveman Jun 07 '11 at 17:31
  • it's as per my comment in @Will's answer - we load modules that store their settings using objects that implement the same interface, but there doesn't seem to be any other way to get the setting instances out. – Simon Jun 07 '11 at 18:11
  • @Simon, can you refactor the modules to register the setting instances on load? – smartcaveman Jun 07 '11 at 18:12
  • I'm afraid not - we could do it in the ones we have access to, but there are others that we don't. – Simon Jun 07 '11 at 18:15
  • @Simon, Is there any reason that you can't use .NET Reflector to access the source of the modules that "you don't have access to"? – smartcaveman Jun 07 '11 at 19:11
  • @smartcaveman - probably on a module-by-module basis. I'm looking for a generic solution. – Simon Jun 07 '11 at 22:12