获取所有公共班级成员 [英] Fetch all public class members

查看:57
本文介绍了获取所有公共班级成员的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我正在编写一个自定义应用程序,以使用反射来获取类的所有公共成员.

每当我在程序集上调用GetTypes()方法时,都会收到以下异常.

无法加载一种或多种请求的类型.检索LoaderExceptions属性以获取更多信息.


内部异常具有以下详细信息


{无法加载文件或程序集" ObjectModel,版本= 1.4.0.18193,文化=中性,PublicKeyToken =空"或其依赖项之一.系统找不到指定的文件.":"ObjectModel,版本= 1.4. 0.18193,文化=中性,PublicKeyToken =空}

ObjectModel程序集是一个自定义程序集,位于与当前加载的程序集相同的目录中.

我有以下代码

Hi,

I am writing a custom application to fetch all the public members of a class using reflection.

Whenever I call the GetTypes() method on the assembly, I get the following exception.

Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.


The inner exception has the following details


{"Could not load file or assembly ''ObjectModel, Version=1.4.0.18193, Culture=neutral, PublicKeyToken=null'' or one of its dependencies. The system cannot find the file specified.":"ObjectModel, Version=1.4.0.18193, Culture=neutral, PublicKeyToken=null"}

ObjectModel assembly is a custom assembly found in the same directory as that of the assembly currently loaded.

I have the following code

private void ProcessAssemblies(IList<string> assemblyNames)
{
    string assemblyName = string.Empty;
    for (int i = 0; i < assemblyNames.Count; i++)
    {
        assemblyName = assemblyNames[i];
        if (File.Exists(assemblyNames[i]))
        {
            Assembly assembly = Assembly.LoadFile(assemblyName);

            PrintAllPublicMembers(assembly);
        }
    }
}

private void PrintAllPublicMembers(Assembly assembly)
{
    foreach (Type type in assembly.GetTypes())
    {
        if (PropertiesCheckBox.Checked)
        {
            IList<PropertyInfo> properties = type.GetProperties(bindingAttributes);
            PrintAllProperties(properties);
        }
        if (MethodsCheckBox.Checked)
        {
            IList<MethodInfo> methods = type.GetMethods(bindingAttributes);
            PrintAllMethods(methods);
        }
    }
}

// The bindingAttributes currently takes the following values
BindingFlags bindingAttributes = BindingFlags.Public | BindingFlags.Instance;





在寻找班级的公开成员时,我是否采取了错误的方法?还是我丢失了什么?





Am I taking the wrong approach in finding the public members of a class? Or am I missing anything?

推荐答案

如果使用GetReferencedAssemblies()assembly查找引用的程序集,您将获得所有程序集的列表. (可能)需要检索完整的类型信息.
然后,您可以使用此信息让用户浏览该程序集并对其进行加载,然后您将需要递归地重复该操作,因为程序集可以引用更多程序集.

希望这会有所帮助,
Fredrik
If you lookup up the referenced assemblies from the assembly using GetReferencedAssemblies() you''ll get a list of all the assemblies that (might) be needed to retrieve full type info.
You can then use this information to have the user browse to were ever that assembly is and load that as well, and then you''ll need to repeat that recursively as assemblies can reference more assemblies.

Hope this helps,
Fredrik


感谢大家的帮助.

我找到了我所面临问题的解决方案.这是我想要实现的完整代码.

程序集加载到的AppDomain尝试自动为引用的程序集解析程序集引用.如果引用的程序集与应用程序位于同一目录中,或者位于GAC中,则程序集解析成功.万一无法解析,则触发"AssemblyResolve"事件.通过订阅此事件,我们可以尝试解析引用.


Thank you all for the help.

I found the solution for the problem I was facing. Here is the complete code for what I was trying to achieve.

The AppDomain to which the assembly is loaded tries to resolve the assembly references for the referenced assemblies automatically. If the referenced assemblies are in the same directory as that of application or if it is in GAC then assembly resolution succeeds. In case it is unable to resolve then "AssemblyResolve" event is fired. By subscribing to this event we can attempt resolving the references.


// Form1.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Reflection;

namespace AssemblyInformation
{
    public partial class Form1 : Form
    {
        BindingFlags bindingAttributes = BindingFlags.Public | BindingFlags.Instance;
        BackgroundWorker workerThread;
        StringBuilder stringBuilder = new StringBuilder();

        public Form1()
        {
            InitializeComponent();

            workerThread = new BackgroundWorker();
            workerThread.DoWork += new DoWorkEventHandler(workerThread_DoWork);
            workerThread.ProgressChanged += new ProgressChangedEventHandler(workerThread_ProgressChanged);
            workerThread.RunWorkerCompleted += new RunWorkerCompletedEventHandler(workerThread_RunWorkerCompleted);
            workerThread.WorkerSupportsCancellation = true;
        }

        void workerThread_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            ResultsTextBox.Text = stringBuilder.ToString();
        }

        void workerThread_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {

        }

        void workerThread_DoWork(object sender, DoWorkEventArgs e)
        {
            IList<string> fileNames = e.Argument as IList<string>;
            ProcessAssemblies(fileNames);
        }

        private void WordWrapCheckBox_CheckedChanged(object sender, EventArgs e)
        {
            ResultsTextBox.WordWrap = WordWrapCheckBox.Checked;
            WordWrapCheckBox.Font = new Font(WordWrapCheckBox.Font, WordWrapCheckBox.Checked ? FontStyle.Bold : FontStyle.Regular);
        }

        private void AttributesCheckBox_CheckedChanged(object sender, EventArgs e)
        {
            CheckBox attributeCheckBox = sender as CheckBox;
            if (attributeCheckBox != null)
            {
                attributeCheckBox.Font = new Font(attributeCheckBox.Font, attributeCheckBox.Checked ? FontStyle.Bold : FontStyle.Regular);
            }
        }

        private void BrowseButton_Click(object sender, EventArgs e)
        {
            if (AssemblyOpenFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                ResultsTextBox.Clear();
                SelectedAssemblyTextBox.Text = AssemblyOpenFileDialog.SafeFileNames.GetCommaSeperatedValue();

                workerThread.RunWorkerAsync(AssemblyOpenFileDialog.FileNames);
            }
        }

        private void ProcessAssemblies(IList<string> assemblyNames)
        {
            try
            {
                string assemblyName = string.Empty;
                this.BeginInvoke((Action)(() => this.Cursor = Cursors.WaitCursor));

                AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(appDomain_AssemblyResolve);
                for (int i = 0; i < assemblyNames.Count; i++)
                {
                    assemblyName = assemblyNames[i];
                    if (File.Exists(assemblyNames[i]))
                    {
                        string path = Path.GetDirectoryName(assemblyName);
                        Directory.SetCurrentDirectory(path);

                        stringBuilder.Append(assemblyName + Environment.NewLine);
                        stringBuilder.Append("---------------------------------" + Environment.NewLine);

                        //Assembly assembly = appDomain.Load(assemblyName);
                        Assembly assembly = Assembly.LoadFile(assemblyName);
                        AppDomain.CurrentDomain.Load(assembly.GetName());
                        IList<assemblyname> referencedAssemblyNames = assembly.GetReferencedAssemblies();

                        foreach (AssemblyName assemblyNameRef in referencedAssemblyNames)
                        {
                            try
                            {
                                AppDomain.CurrentDomain.Load(assemblyNameRef);
                            }
                            catch (FileNotFoundException)
                            {
                                string referencedAssemblyPath = path + "\\" + assemblyNameRef.Name + ".dll";
                                AppDomain.CurrentDomain.Load(referencedAssemblyPath);
                            }
                        }
                        PrintAllPublicMembers(assembly);
                    }
                }
            }
            finally
            {
                this.BeginInvoke((Action)(() => this.Cursor = Cursors.Default));
            }
        }

        Assembly appDomain_AssemblyResolve(object sender, ResolveEventArgs args)
        {
            string path = Path.GetDirectoryName(AssemblyOpenFileDialog.FileName) + "\\" + args.Name.Substring(0, args.Name.IndexOf(",")) + ".dll";

            //Retrieve the list of referenced assemblies in an array of AssemblyName.
            Assembly MyAssembly = null;

            //Load the assembly from the specified path. 					
            if (File.Exists(path))
                MyAssembly = Assembly.LoadFrom(path);
            else
            {
                this.Invoke((Action)(() =>
                {
                    OpenFileDialog resolveAssemblyFileDialog = new OpenFileDialog();
                    resolveAssemblyFileDialog.FileName = args.Name.Substring(0, args.Name.IndexOf(",")) + ".dll";
                    resolveAssemblyFileDialog.Filter = resolveAssemblyFileDialog.FileName + "|" + resolveAssemblyFileDialog.FileName;
                    resolveAssemblyFileDialog.Multiselect = false;
                    if (resolveAssemblyFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                    {
                        MyAssembly = Assembly.LoadFrom(resolveAssemblyFileDialog.FileName);
                    }
                    else
                    {
                        DialogResult appClosureConfirmationDialogResult = MessageBox.Show("Unable to proceed without resolving reference to the '" + args.Name + "' assembly. Do you want to try again?", "Assembly Information", MessageBoxButtons.YesNo, MessageBoxIcon.Error, MessageBoxDefaultButton.Button2);
                        if (appClosureConfirmationDialogResult == System.Windows.Forms.DialogResult.Yes)
                        {
                            if (resolveAssemblyFileDialog.ShowDialog(this) == System.Windows.Forms.DialogResult.OK)
                            {
                                MyAssembly = Assembly.LoadFrom(resolveAssemblyFileDialog.FileName);
                            }
                            else
                            {
                                Application.Exit();
                            }
                        }
                        else
                            Application.Exit();
                    }
                }));
            }
            //Return the loaded assembly.
            return MyAssembly;
        }

        private void PrintAllPublicMembers(Assembly assembly)
        {
            foreach (Type type in assembly.GetTypes())
            {
                stringBuilder.Append("Class/Interface: " + type.Name + Environment.NewLine);
                stringBuilder.Append("\tProperties: " + Environment.NewLine);
                if (PropertiesCheckBox.Checked)
                {
                    IList<propertyinfo> properties = type.GetProperties(bindingAttributes);
                    PrintAllProperties(properties);
                }
                stringBuilder.Append("\tMethods: " + Environment.NewLine);
                if (MethodsCheckBox.Checked)
                {
                    IList<methodinfo> methods = type.GetMethods(bindingAttributes);
                    PrintAllMethods(methods);
                }
            }
        }

        private void PrintAllMethods(IList<methodinfo> methods)
        {
            foreach (var method in methods)
            {
                stringBuilder.Append("\t\t" + method.Name + Environment.NewLine);
            }
        }

        private void PrintAllProperties(IList<propertyinfo> properties)
        {
            foreach (PropertyInfo property in properties)
            {
                IList<object> customAttributes = property.GetCustomAttributes(false);
                foreach (var item in customAttributes)
                {

                }
                stringBuilder.Append("\t\t" + property.Name + Environment.NewLine);
            }
        }

        private void TypeAttributesCheckBox_CheckedChanged(object sender, EventArgs e)
        {
            CheckBox attributeCheckBox = sender as CheckBox;
            if (attributeCheckBox != null)
            {
                attributeCheckBox.Font = new Font(attributeCheckBox.Font, attributeCheckBox.Checked ? FontStyle.Bold : FontStyle.Regular);
            }
        }

        private void FindButton_Click(object sender, EventArgs e)
        {

        }
    }
}





// ExtentionMethods.cs

    internal static class ExtensionMethods
    {
        public static string GetCommaSeperatedValue(this IList<string> stringArray)
        {
            string output = string.Empty;

            if (stringArray.Count == 0)
                return output;
            else if (stringArray.Count == 1)
                return (output = stringArray[0]);
            else
            {
                for (int i = 0; i < stringArray.Count; i++)
                {
                    output += "\"" + stringArray[i] + "\"";
                    if (i < (stringArray.Count - 1))
                    {
                        output += " ";
                    }
                }

                return output;
            }
        }
    }
</string>


这篇关于获取所有公共班级成员的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆