0

I'm trying to access all the user declared classes in my project. My goal is calling functions of the classes that I access. I have researched this for 2-3 days, but I couldn't find any solutions.

I have tried to get types from assembly but it gave me so complicated results. Here is what I tried:

Assembly assembly = AppDomain.CurrentDomain.GetAssemblies();
Type[] types = assembly.GetTypes();

int i;
for ( i = 0 ; i < types.Length ; i++ )
{
    Console.WriteLine( types[ i ].Name );
}

Quick Example - If any other programmer that works on the project creates a class called "Hello", I need to get that class and call the required function inside of it.

I'm stuck with the "getting user/programmer declared classes" part, any help is great.


Update: Thanks to everyone for helping me out. I managed the solve this problem by creating a custom attribute just like how @Ghost4Man suggests. My new code looks like this:

public void Test()
{
    foreach ( Assembly a in AppDomain.CurrentDomain.GetAssemblies() )
    {
        Type[] array = a.GetTypes();
        for ( int i = 0 ; i < array.Length ; i++ )
        {
            Type t = array[ i ];
            DConsoleRequired dConsoleRequired = ( DConsoleRequired )
                t.GetCustomAttributes( typeof( DConsoleRequired ) , false )[ 0 ];
            if ( dConsoleRequired != null )
            {
                Debug.Log( t.Name );
            }
        }
    }
}

Update 2 : Updated code

public void Test2()
{
        Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
        Type[] types = new Type[ assemblies.Length ];

        int i;
        for ( i = 0 ; i < assemblies.Length ; i++ )
        {
            types = assemblies[ i ].GetTypes();

            for ( int j = 0 ; j < types.Length ; j++ )
            {
                var type = types[ j ];
                if ( ConsoleRequiredAttribute.IsDefined( type , typeof( ConsoleRequiredAttribute ) ) )
                {
                    Debug.Log( type.Name );
                }
            }            
        }
 }
I.Ozsaygi
  • 13
  • 3
  • "it gave me so complicated results" What results do you get? What did you expect instead? Did you see this thread to load a type from an assembly at runtime: https://stackoverflow.com/questions/465488/can-i-load-a-net-assembly-at-runtime-and-instantiate-a-type-knowing-only-the-na? – MakePeaceGreatAgain Oct 17 '18 at 14:23
  • What exactly do you mean when saying "_user declared classes_"? More precisely, what would differentiate your so-called "_user declared classes_" from other classes/types? –  Oct 17 '18 at 14:25
  • @elgonzo What i mean with "user declared" is classes that you create yourself. Instead of other system classes. – I.Ozsaygi Oct 17 '18 at 14:29
  • That sounds like a XY problem to me. Why exactly do you attempt to find classes you wrote yourself inside the compiled code? What is the underlying problem here you try to solve with this approach? –  Oct 17 '18 at 14:30
  • You can filter out CLR types by namespace. Take a look at [this](https://stackoverflow.com/q/79693/4685428) question – Aleks Andreev Oct 17 '18 at 14:32
  • @HimBromBeere Thanks for your answer i am checking it. – I.Ozsaygi Oct 17 '18 at 14:32
  • @elgonzo I am trying to enable other users to see classes and it's functions from an user interface system , like forms or windows. – I.Ozsaygi Oct 17 '18 at 14:34
  • You mean, some form of scripting, plug-in or extension mechanism? –  Oct 17 '18 at 14:35
  • @elgonzo Yes , it is a tool for development team to see programmer declared classes and it's functions from some interface (interface can be windows forms) – I.Ozsaygi Oct 17 '18 at 14:36
  • 1
    I would then suggest you create one or more interfaces that declare the methods you want to call. The classes from other programmers will then need to implement those interfaces (it forces them to implement a method your "user interface program" will understand and can execute). When obtaining types from an assembly, you can then check and filter whether a type implements one of those interfaces. (Define those interfaces in their own little assembly project, and let your UI program as well as the other programmers use the assembly created by this little project as a dependency) –  Oct 17 '18 at 14:46
  • (By the way, my last comment is in addition to HimBromBeere's suggestion. Load the assembly/ies produced by the other programmers "manually" at runtime - per HimBromBeere's suggestion - and then enumerate/filter all the types from those assemblies that implement your interfaces...) –  Oct 17 '18 at 14:53

2 Answers2

1

You can annotate the classes with a custom attribute and then filter the types in the assembly by checking if GetCustomAttribute returns null:

using System.Reflection;

[AttributeUsage(AttributeTargets.Class)]
class HelloAttribute : Attribute { }

[Hello]
class Hello1 { }

[Hello]
class Hello2 { }

and then:

if (types[i].GetCustomAttribute<HelloAttribute>() != null)
{
    // do something with the class
}

Or check if the class implements a specific interface:

if (typeof(IHello).IsAssignableFrom(types[i]))
{
    // do something with the class
}
Ghost4Man
  • 1,040
  • 1
  • 12
  • 19
1

I wrote a small Console application that addresses your need. You can load assembly dynamically and then inspect it's members.

class Program
{
    static void Main(string[] args)
    {
        var assembly = Assembly.LoadFrom("SomeLibrary.dll");
        var types = assembly.GetTypes();

        foreach (var type in types)
        {
            Console.WriteLine($"Type name: {type}");

            var functions = type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
            foreach (var function in functions)
            {
                Console.WriteLine($"Function name: {function.Name}");

                var instance = Activator.CreateInstance(type, null, null);
                var response = function.Invoke(instance, new[] { "Hello from dynamically loaded assembly" });

                Console.WriteLine($"Function response: {response}");
            }
        }
        Console.ReadLine();
    }
}

It assumes you have all functions that take in one string parameter.

Alias
  • 341
  • 2
  • 3
  • 14