反思与应用设计

让我来描述一下我现在遇到的问题和解决方案,也许你可以帮助我了解为什么这是一个坏主意(假设它是)以及我能做些什么来使它成为一个更好的系统。

现在我有600个“裂土器”解析文件并将它们翻录成csv或其他格式。 裂土器都实现了一个通用的接口和基类。 当作业排队时,取决于该作业的配置,使用reflection调用特定的开膛手。

foreach (var stream in streams) { try { // load it Assembly asm = Assembly.LoadFile(Path.Combine(stream.RipperPath, stream.RipperFileName), new Evidence()); if (asm == null) { MessageBox.Show(String.Format("Invalid Interface ripper loaded.\n{0}", Path.Combine(stream.RipperPath, stream.RipperFileName))); return; } foreach (Type objType in asm.GetTypes()) { if (!objType.IsPublic) continue; // make sure the type isn't Abstract if (((objType.Attributes & TypeAttributes.Abstract) == TypeAttributes.Abstract)) continue; // IRipper is the interface that all of the Rippers must implement to be loaded Type objInterface = objType.GetInterface("IRipper", true); if (objInterface == null) continue; try { var iri = (IRipper)Activator.CreateInstance(objType); // Rippers must register with their hosts iri.Host = this; iri.OnStart += RipperStart; iri.OnComplete += RipperComplete; iri.OnProgressChanged += RipperStatusUpdate; iri.dataStream = stream; } catch (Exception ex) { Console.WriteLine(ex.Message); } } } catch (Exception ex) { MessageBox.Show(String.Format("Error loading interface: {0}\n{1}", Path.Combine(stream.RipperPath, stream.RipperFileName), ex.Message)); } } 

所有的rippers都实现了一个名为“Rip()”的函数,接口将它们收缩。

使用当前代码我唯一能看到的问题是,在加载600个程序集后(因为它们在需要时加载)如果它们在使用后没有卸载,它将开始变慢。

你会建议什么?

你真的有600个不同的裂土器,或600个流和一些较少数量的裂土器? 你真的需要每个裂土器都在自己的assembly中吗? 如果你可以将裂土器聚集在一起,你可以拥有更少的组件。 如果你的流细节包含类型名称和可执行文件,你可以有多个rippers,你不需要为它们查看程序集 – 只需调用Assembly.GetType

我不知道每个组件有多少开销,请注意 – 我希望600个组件占用相当多的内存,但不会影响性能。

整体方法似乎是合理的,尽管您可能还想查看托管可扩展性框架(MEF) – 它可能对您的案例来说太过分了,但值得一看。 我要做的另一件事是从“处理流”代码中分解“获得一个开膛手”:)

您可能想看看System.Addin的东西。 看起来加载项已加载到他们自己的应用程序域中,这使得可以在不再需要时干净地卸载它们。