Get methods and attributes from dll assembly

2019-09-14 06:11发布

问题:

I'm trying to get a small plugin mechanism running by reflecting an dll file providing my class Plugin (implementing my Plugin-Interface shared among dll and main project / sorry for naming both the same) offering an attribute of type string and a main-method activate:

Interface:

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

dll class:

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

So here comes the problem, there is no type named "Plugin" to be found in the assembly. Tried to get all types from all assemblies in the directory, get all methods/members/custom attributes from them, have them logged etc, but there is nothing of my class Plugin to be found, while the dll definitely is being found, as it doesn't return the 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);
            }

I know my code probably looks really messy to you all - I think the last try-block is the only thing relevant here, wanted to put in the class itself and the interface for a little bit transparency though - and my english isn't perfect, but I hope someone can help me out finding my attribute+method in the assembly.

EDIT:

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

                    }

I did change it according to Getting all types in a namespace via reflection Still the same result, what did I do wrong?

回答1:

As pointed out by @stuartd:

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

is the solution, missed the namespace

cb.Items.Add("Modification");

doesn't work though...any suggestions?

Got it to work getting the form's children by Controls["nameOfChild"] directly, that help method to fetch all objects by class seems to be wrong here.

Plugin works now, thanks!