Получить методы и атрибуты из сборки dll

Я пытаюсь запустить небольшой механизм плагинов, отражая файл dll, предоставляющий мой класс Plugin (реализующий мой Plugin-интерфейс, общий для dll и основного проекта/извините за то, что я называю одно и то же), предлагая атрибут типа string и main- метод activate:

Интерфейс:

public interface Plugin
{
    string pluginName{get;set;}
    void activate(System.Windows.Forms.Form main);
}

DLL класс:

    public class Plugin : WhiteA.Plugin
        {
            public string pluginName{get;set;}

            public void activate(System.Windows.Forms.Form main){
                //find the right form to modify it
                IEnumerable<System.Windows.Forms.ComboBox> ie= GetControlsOfType<System.Windows.Forms.ComboBox>(main);
                System.Windows.Forms.ComboBox cb=GetControlsOfType<System.Windows.Forms.ComboBox>(main).FirstOrDefault();
                cb.Items.Add("Modification");
                System.Windows.Forms.MessageBox.Show(cb.SelectedItem.ToString());
            }

            public static IEnumerable<T> GetControlsOfType<T>(System.Windows.Forms.Control root)
                where T : System.Windows.Forms.Control
            {
                var t = root as T;
                if (t != null)
                    yield return t;

                var container = root as System.Windows.Forms.ContainerControl;
                if (container != null)
                    foreach (System.Windows.Forms.Control c in container.Controls)
                        foreach (var i in GetControlsOfType<T>(c))
                            yield return i;
            }
        }

Итак, вот проблема: в сборке нет type с именем "Plugin". Пытался получить все типы из всех сборок в каталоге, получить от них все методы/члены/пользовательские атрибуты, зарегистрировать их и т. д., но ничего из моего класса Plugin не найдено, в то время как dll определенно находится, так как он не возвращает MessageBox.

string[] files=new string[]{};
            string path="Error retrieving path";
            try{
                path = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
                files = System.IO.Directory.GetFiles(path, "*.dll");
            }catch(Exception exF){

            }
            if(files.Length>0){
                foreach (string dll in files){
                    try{
                        System.Reflection.Assembly sampleAssembly = System.Reflection.Assembly.LoadFrom(dll);
                        Type myType = sampleAssembly.GetType("Plugin");
                        System.Reflection.MethodInfo method = myType.GetMethod("activate");
                        object myInstance = Activator.CreateInstance(myType);
                        method.Invoke(myInstance, new object[]{this});
                    }catch(Exception exL){

                    }
                }
            }else{
                MessageBox.Show("No working plugins detected in " + path.ToString(), "Nothing to activate", MessageBoxButtons.OK,  MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1);
            }

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

ИЗМЕНИТЬ:

                    try{
                        System.Reflection.Assembly sampleAssembly = System.Reflection.Assembly.LoadFrom(dll);

                        List<Type> list= sampleAssembly.GetTypes().Where(p =>
                                             p.Namespace == dll &&
                                             p.Name.Contains("Plugin")
                                            ).ToList();
                        Type myType=list.FirstOrDefault();

                        //Type myType = sampleAssembly.GetType("Plugin");
                        System.Reflection.MethodInfo method = myType.GetMethod("activate");
                        object myInstance = Activator.CreateInstance(myType);
                        method.Invoke(myInstance, new object[]{this});

                    }

Я изменил его в соответствии с Получение всех типов в пространстве имен через отражение Все тот же результат, что я сделал не так?


person Community    schedule 01.06.2017    source источник
comment
Я думаю, вам нужно передать пространство имен GetType()? как например sampleAssembly.GetType("MyApp.Plugins.Plugin");? Обратите внимание, что вы не должны передавать имя сборки — см. документы   -  person stuartd    schedule 01.06.2017
comment
На это был дан ответ здесь. stackoverflow.com/questions/79693/   -  person JWP    schedule 01.06.2017
comment
@stuartd это означало бы, что все мои плагины должны иметь одно и то же пространство имен, верно? Это необходимо/разрешено?   -  person    schedule 01.06.2017
comment
Пока они все в разных сборках, тогда все в порядке.   -  person stuartd    schedule 01.06.2017


Ответы (1)


Как отметил @stuartd:

Type myType = sampleAssembly.GetType("WhiteA_Plugin_PausedVideo.Plugin");

это решение, пропустил пространство имен

cb.Items.Add("Modification");

не работает, хотя... есть предложения?

Заработало получение дочерних элементов формы с помощью Controls["nameOfChild"] напрямую, этот метод помощи для получения всех объектов по классам кажется здесь неправильным.

Плагин работает, спасибо!

person Community    schedule 05.07.2017