Отражение и дизайн приложения - PullRequest
1 голос
/ 16 марта 2009

Позвольте мне описать проблему и решение, которое у меня есть на данный момент, и, возможно, вы поможете мне понять, почему это плохая идея (если она есть) и что я могу сделать, чтобы сделать ее лучшей системой.

сейчас у меня есть 600 "рипперов", которые анализируют файлы и копируют их в csv или другие форматы. все рипперы реализуют общий интерфейс и базовый класс. В момент, когда задание ставится в очередь в зависимости от конфигурации этого задания, конкретный риппер вызывается с помощью отражения.

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

все рипперы имеют функцию "Rip ()", с которой интерфейс заключает с ними контракт.

при использовании текущего кода единственная проблема, которую я вижу, состоит в том, что после загрузки 600 сборок (так как они загружаются, когда они необходимы), он начнет работать немного медленнее, если они не будут выгружены после того, как они были использованы.

Что бы вы предложили?

Ответы [ 2 ]

1 голос
/ 16 марта 2009

У вас есть 600 различных рыхлителей, или 600 потоков и немного меньшее количество рыхлителей? Вам действительно нужно, чтобы каждый рыхлитель находился в отдельной сборке? Если бы вы могли собрать рыхлители вместе, у вас могло бы быть гораздо меньше сборок. Если данные вашего потока содержат как имя типа, так и исполняемый файл, у вас может быть несколько рипперов, и вам не нужно будет просматривать их для сборки - просто вызовите Assembly.GetType.

Я не знаю, сколько на самом деле накладных расходов на каждую сборку, заметьте, я бы ожидал, что 600 сборок займут достаточное количество памяти, но не окажут существенного влияния на производительность.

Общий подход кажется разумным, хотя вы также можете взглянуть на Managed Extensibility Framework (MEF) - это может быть излишним для вашего случая, но стоит посмотреть. Другая вещь, которую я хотел бы сделать, это исключить «получение риппера» из кода «обработка потока»:)

0 голосов
/ 16 марта 2009

Возможно, вы захотите взглянуть на System.Addin . Похоже, что надстройки загружаются в свои собственные домены приложений, что позволяет аккуратно выгружать их, когда они больше не нужны.

...