23

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

5 Answers 5

23

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.

Sign up to request clarification or add additional context in comments.

6 Comments

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.
+1 thanks. Added the cast to T which made the code compile for me.
This will fail for types that aren't exportable to the calling assembly, but there is a fix for that, if you look...
This is enumerating through all types defined in your referenced assemblies, not all instances of those types.
@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. 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!
|
10

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

1 Comment

I asked essentially the same question in c# - Enumerate all instances of a class. Can Profiling (as in Profiling Overview) be used? What about CodeInject or dI.Hook?
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)

Comments

3

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

1 Comment

I'm afraid they're not all ours.
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[] {};
}

7 Comments

nice - but how do I get the instances of those types?
@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... What is your use case?
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, can you refactor the modules to register the setting instances on load?
I'm afraid not - we could do it in the ones we have access to, but there are others that we don't.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.