0

My program is, said shortly, comparing algorithms. At the moment I have to change code whenever i add or remove certain algorithms. I am using C#.

My idea was to just check for classes in a directory and then for every object in that directory instantiate it in a list (or dictionary but i don't really understand those yet, but for now lets say list). That way I don't have to add every algorithm manually and can just add or remove classes by adding or removing them from said folder.

So whenever I compile my program it goes through src/model/algorithms, takes every file which is a c# class and then adds an instance of that class into a list.

Is this possible, and how would I do this?

  • 1
    How can a directory contain "classes"? Do you want to compile C# files on demand? Or do you want a plugin-like system, that loads _assemblies_ containing classes on demand? Both questions have been asked and answered before, try searching. – CodeCaster Jun 18 '19 at 09:46
  • Whenever I compile my program I want to check if in src/model/algorithms contains files which are classes, and then instantiate those. I tried researching this but didn't find anything – user11350058 Jun 18 '19 at 09:48
  • You really gotta describe your scenario better. Do you want to deliver your source files with your executable? I guess not. This really sounds like an XY problem. This has nothing to do with source files. What I _think_ you want, is to find all "algorithm" types that live in your executable. For that either whitelist a certain namespace, or let all your algorithms implement a certain interface. Then upon application startup, scan all types for that namespace or interface, and instantiate them. – CodeCaster Jun 18 '19 at 09:54
  • @CodeCaster I'm amazed. I came into this thinking i know a fair bit and after understanding nothing of what you said I am reassured that I actually know nothing. Explaining it to all of my capabilities I wanna press f5, and that instead of me instantiating every algorithm manually I want the contoller to instantiate everything in my /algorithms/folder – user11350058 Jun 18 '19 at 10:09
  • The point is that your executable has no relation to your source files. They're compiled _into_ your executable, and you don't want to deliver your source files with your executable. There's simply no need to. See my answer below, and check whether that does what you want. – CodeCaster Jun 18 '19 at 10:10
  • @CodeCaster it's a lot of new concepts(like interfaces etc.) for me so it might take a while but I'll let ya know. – user11350058 Jun 18 '19 at 10:16

2 Answers2

2

As far as I understand, you're writing an executable that has to run some "algorithms". Your algorithms are implemented as classes that live in your executable's assembly. You don't want to hardcode which algorithms the executable has to execute, but you want them to be automatically discoverable.

Then simply define an interface:

public interface IAlgorithm
{
    string Name { get; }

    void Execute();
}

And let your algorithms implement this interface:

public class FooAlgorithm : IAlgorithm
{
    public string Name => "Foo";

    public void Execute()
    {
        Console.WriteLine("Fooing the foo");
    }
}

public class BarAlgorithm : IAlgorithm
{
    public string Name => "Bar";

    public void Execute()
    {
        Console.WriteLine("Barring the bar");
    }
}

Now upon program startup, scan your assembly for types implementing this interface:

var algorithmTypes = AppDomain.CurrentDomain.GetAssemblies()
    .SelectMany(s => s.GetTypes())
    .Where(p => typeof(IAlgorithm).IsAssignableFrom(p))
    .ToList();

foreach (var algorithmType in algorithmTypes )
{
    var algorithm = (IAlgorithm)Activator.CreateInstance(algorithmType);
    Console.WriteLine($"Executing algorithm '{algorithm.Name}'...");
    algorithm.Execute();
}

So you see, this has nothing to do with class files.

CodeCaster
  • 147,647
  • 23
  • 218
  • 272
  • I already have another abstract class "algotithm" and my algotithms look like class Bubbelsort : Algorithm. can i just add :IAlgotithm? – user11350058 Jun 18 '19 at 10:21
  • Then you can omit the entire `IAlgorithm` route, and use `Algorithm` instead. So don't create an interface, and replace `IAlgorithm` in the code above with `Algorithm`. – CodeCaster Jun 18 '19 at 10:24
  • with the .Where(p => type. it gives me a the name 'type' does not exist in the current context, do you know why? – user11350058 Jun 18 '19 at 10:32
  • @user11350058: I think that's a typo. It should be `type => type`. The part with the `=>` is a [lambda function](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/statements-expressions-operators/lambda-expressions). The parameters are declared to the left of it, and the body to the right. – vyrp Jun 18 '19 at 18:44
  • Also I think it might be swapped. It should be: `typeof(IAlgorithm).IsAssignableFrom(type)`. – vyrp Jun 18 '19 at 18:48
  • @user11350058 vyrp is right, I've updated my answer. – CodeCaster Jun 19 '19 at 06:39
0

First you need to get all the file names from your directory:

DirectoryInfo d = new DirectoryInfo(@"PATHHERE");
FileInfo[] Files = d.GetFiles("*.cs"); //Getting cs files
string str = "";
foreach(FileInfo file in Files )
{
  //USE THE "file.Name" TO INSTANTIATE THE CLASS (CHECK THE CODE ABOVE)
}

Now for each name you can use the Activator.CreateInstance():

myObject = (MyAbstractClass)Activator.CreateInstance("AssemblyName", "TypeName");

or

var type = Type.GetType("MyFullyQualifiedTypeName");
var myObject = (MyAbstractClass)Activator.CreateInstance(type);
leandro.andrioli
  • 997
  • 5
  • 12
  • Except a filename doesn't have to correspond to the class name it contains, a file can be empty or a file can contain multiple classes(or struct[s] or interface[s]), and you don't want to deliver your source files with your executable just to enable this functionality. – CodeCaster Jun 18 '19 at 09:53
  • @CodeCaster I'm not delivering a complete solution, it's just a sample to clarify the idea in general (even because the scenario that was asked is at a high level and lacks details). – leandro.andrioli Jun 18 '19 at 10:00