This is the 9th day of my participation in Gwen Challenge

We’ve been writing programs in C# for a long time. We use inheritance, polymorphism, interfaces, and generics when we write programs. We know that subclasses can inherit abstract classes and override abstract methods from their parent classes. 1, Every tree must have roots and leaves, class inheritance is the same, how to find all through the assembly name inherited from the parent class and so on assembly name? 2, If program B is called by other programs, how to query all programs that call B through the assembly? How to query which assemblies are referenced by the current project?

A, query

Query BaseType, a collection of programs that inherit from a parent class

The.net Assembly Object Assembly has a BaseType attribute that returns the BaseType of the current Assembly. The default is Object. Using this property, you can determine whether an assembly inherits a parent class.

Assembly B is referenced by program A, which gets information about assembly A, GetCallingAssembly

The.net Assembly object Assembly has a method called GetCallingAssembly to get information about the parent Assembly that the current Assembly is called from.

Find the assembly GetAssemblies for the current project

For the current project all assemblies System. The method of AppDomain. CurrentDomain. GetAssemblies ();

Instantiate an object

GetType() gets the data type of the assembly. Activator.createinstance (type) creates the instance object of the response.

BaseService is the base class of all service classes

List<Type> TypeItemList = new List<Type>();
            //var ResultTypeList = Assembly.GetEntryAssembly();
            //if (ResultTypeList == null)
            //{
            //    ResultTypeList = Assembly.GetCallingAssembly();
            //    var ItemList = ResultTypeList.GetReferencedAssemblies().Where(p => p.GetType() == typeof(BaseService));                
            //}
            Assembly[] AssbyCustmList = System.AppDomain.CurrentDomain.GetAssemblies();
            foreach (Assembly assItem in AssbyCustmList)
            {
                TypeItemList.AddRange(assItem.GetTypes().Where(x => x.BaseType == typeof(BaseService)).ToList());
            }
            //IEnumerable<Type> TypeItemList = CurType.Assembly.GetExportedTypes().Where(x => x.BaseType == typeof(BaseService)).ToList();
            //IEnumerable<Type> TypeItemList = ResultTypeList.GetTypes().Where(x => x.BaseType == typeof(BaseService)).ToList();
            BaseService TarService = null;
            foreach (Type typeitem in TypeItemList)
            {
                if (_Reporttory.Count(p => p.GetType() == typeitem) == 0)
                {
                    TarService = (Activator.CreateInstance(typeitem) as BaseService);
                }
                else
                {
                    TarService = _Reporttory.First(p => p.GetType() == typeitem);
                }
                TarService.Start();
            }         
Copy the code

The test code

 static void ShowAssemblyDetail(Assembly assembly, string name = "")
        {
            Console.WriteLine("============ \n");
            Console.WriteLine("FullName:" + assembly.FullName);
            Console.WriteLine("CodeBase:" + assembly.CodeBase);
            Console.WriteLine("EscapedCodeBase:" + assembly.EscapedCodeBase);
            Console.WriteLine("GlobalAssemblyCache:" + assembly.GlobalAssemblyCache);
            Console.WriteLine("HostContext:" + assembly.HostContext);
            Console.WriteLine("ImageRuntimeVersion:" + assembly.ImageRuntimeVersion);
            Console.WriteLine("IsDynamic:" + assembly.IsDynamic);
            Console.WriteLine("IsFullyTrusted:" + assembly.IsFullyTrusted);
            Console.WriteLine("Location:" + assembly.Location);
            Console.WriteLine("ReflectionOnly:" + assembly.ReflectionOnly);
            Console.WriteLine("SecurityRuleSet:" + assembly.SecurityRuleSet);
        }
Copy the code

Two, loading method

There are three common methods for reflection in.NET: assembly.load () assembly.loadFrom () assembly.loadfile ()

1: the Assembly. The Load ()

The Load() method takes a String or AssemblyName as an argument, which is actually a strong name (AssemblyName, version, language culture, public key token) of the assembly that needs to be loaded. It loads other assemblies referenced by this assembly, and this method should generally be preferred because it is much more efficient than LoadFrom and does not cause reloading problems (for reasons explained in point 2). When using this method, the CLR applies a certain strategy to find assemblies. In fact, the CLR locates assemblies in the following order: (1) If an assembly has a strong name, it looks for assemblies in the global assembly cache (GAC) first. ⑵ If the strong name of the assembly is not specified correctly or not found in the GAC, then the CLR will detect the specific folder by using the URL specified by the element in the configuration file: Suppose your application directory is C:\AppDir, the privatePath element specifies a path Path1, and the assembly you want to locate is AssemblyName.dll. The CLR will locate the assembly C:\AppDir\ Assemblyname.dll C:\AppDir\AssemblyName\ Assemblyname.dll C: \ AppDir \ Path1 \ AssemblyName DLL C: \ AppDir \ Path1 \ AssemblyName \ AssemblyName DLL

If the above methods cannot find the assembly, a compilation error will occur, or if the assembly is dynamically loaded, an exception will be thrown at runtime!

2: Assembly. LoadFrom ()

This method from the specified path to Load the assembly, in fact, this method is invoked, the CLR will open this file, through the assembly AssemblyRef metadata table lookup, learned that all assembly references and need to get the assembly version, language, culture, public key tag information, such as his transfer to the Load method, The Load method then uses the above strategy to find the assembly. If an assembly is found, it is compared with the path specified in the LoadFrom method. If the path is the same, the assembly is considered part of the application. If the path is different or the Load method does not find the assembly, the assembly is simply loaded as a “data file” and is not considered part of the application. This is why the Load method mentioned in Point 1 is more efficient than the LoadFrom method. Also, since it is possible to load assemblies as “data files,” using LoadFrom to load the same assembly from different paths results in repeated loading. Of course this method loads other assemblies referenced by this assembly. Assembly.LoadFrom(@”C:\ABC\Test.dll”);

3: Assembly. LoadFile ()

This method loads the assembly from the specified file. The difference is that this method does not load other assemblies referenced by this assembly. You need to control and display all dependent assemblies.

Conclusion: In general, you should use the Load method first to Load an assembly. If you need to use the LoadFrom method, you should change the design and use the Load method instead.

Difference between LoadFile and LoadFrom

Assembly.LoadFile only loads the corresponding DLL file, such as Assembly.LoadFile(“abc.dll”), then loads abc.dll. Assemblies.LoadFrom, on the other hand, loads the DLL file and any other DLLS it references, such as def.dll in the example above.

DLL has two versions (version 1 is in directory 1 and version 2 is in directory 2). The program starts with version 1 loaded. When version 2 is loaded with assembly.loadFrom (“2\abc.dll”), version 1 is returned instead of loading. Assembly.LoadFile does not do this check, for example, if the above example is replaced with Assembly.LoadFile, version 2 will load correctly. LoadFile: loads the contents of the assembly file on the specified path. LoadFrom: Loads the contents of an assembly file based on the assembly file name.

The difference between:

The LoadFile method is used to load and examine assemblies with the same identity but in different paths. But no program dependencies are loaded. LoadFrom cannot be used to load assemblies with the same identity but different paths.