【问题标题】:Is there a way to check a folder for classes and then instantiate them automatically?有没有办法检查文件夹中的类,然后自动实例化它们?
【发布时间】:2019-06-18 09:44:25
【问题描述】:

简短地说,我的程序是比较算法。目前,每当我添加或删除某些算法时,我都必须更改代码。我正在使用 C#。

我的想法是只检查目录中的类,然后为该目录中的每个对象在列表中实例化它(或字典,但我还不太了解这些,但现在让我们说列表)。这样我就不必手动添加每个算法,并且可以通过在所述文件夹中添加或删除类来添加或删除类。

所以每当我编译我的程序时,它都会通过 src/model/algorithms,获取每个属于 c# 类的文件,然后将该类的一个实例添加到列表中。

这可能吗?我该怎么做?

【问题讨论】:

  • 目录如何包含“类”?您想按需编译 C# 文件吗?或者您想要一个类似插件的系统,可以按需加载包含类的程序集?这两个问题都曾被问过和回答过,请尝试搜索。
  • 每当我编译我的程序时,我想检查 src/model/algorithms 中是否包含类文件,然后实例化这些文件。我试图研究这个,但没有找到任何东西
  • 你真的需要更好地描述你的场景。你想用你的可执行文件交付你的源文件吗?我猜不是。这听起来确实像一个 XY 问题。这与源文件无关。我认为你想要的是找到所有存在于你的可执行文件中的“算法”类型。为此,要么将某个命名空间列入白名单,要么让所有算法实现某个接口。然后在应用程序启动时,扫描该命名空间或接口的所有类型,并实例化它们。
  • @CodeCaster 我很惊讶。我进入这个想法我知道一点点,在对你所说的一无所知之后,我确信我实际上一无所知。向我的所有功能解释它我想按 f5,而不是我手动实例化每个算法,我希望控制器实例化我的 /algorithms/文件夹中的所有内容
  • 关键是您的可执行文件与您的源文件无关。它们被编译您的可执行文件中,您不希望将源文件与您的可执行文件一起交付。根本没有必要。请参阅下面的答案,并检查这是否符合您的要求。

标签: c# oop instantiation


【解决方案1】:

据我了解,您正在编写一个必须运行一些“算法”的可执行文件。您的算法被实现为存在于可执行文件程序集中的类。您不想硬编码可执行文件必须执行的算法,但希望它们能够自动被发现。

然后简单定义一个接口:

public interface IAlgorithm
{
    string Name { get; }

    void Execute();
}

让你的算法实现这个接口:

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");
    }
}

现在在程序启动时,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();
}

所以你看,这与类文件无关。

【讨论】:

  • 我已经有了另一个抽象类“算法”,我的算法看起来像 Bubbelsort 类:算法。我可以添加:IAlgotithm 吗?
  • 那么你可以省略整个IAlgorithm路由,而使用Algorithm。所以不要创建接口,将上面代码中的IAlgorithm替换为Algorithm
  • 带有 .Where(p => 类型。它给了我一个名称 'type' 在当前上下文中不存在,你知道为什么吗?
  • @user11350058:我认为这是一个错字。应该是type => type。带有=> 的部分是lambda function。参数声明在它的左边,而主体声明在右边。
  • 我也认为它可能会被交换。应该是:typeof(IAlgorithm).IsAssignableFrom(type).
【解决方案2】:

首先你需要从你的目录中获取所有的文件名:

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)
}

现在对于每个名称,您都可以使用 Activator.CreateInstance():

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

var type = Type.GetType("MyFullyQualifiedTypeName");
var myObject = (MyAbstractClass)Activator.CreateInstance(type);

【讨论】:

  • 除了文件名不必与它包含的类名相对应,文件可以为空或文件可以包含多个类(或结构[s]或接口[s]),并且您不想仅仅为了启用此功能而将源文件与可执行文件一起交付。
  • @CodeCaster 我没有提供一个完整的解决方案,它只是一个示例来阐明这个想法(即使是因为所询问的场景处于高水平并且缺乏细节)。
猜你喜欢
  • 2014-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-23
  • 2016-05-08
  • 1970-01-01
  • 2011-08-03
  • 1970-01-01
相关资源
最近更新 更多