private MsilFile GetWrapperSource(PluginType pluginType, string[] methodsToRemoveFromWrapper, string pluginAssemblyName, string pluginClass) { var wrapperType = Wrapper[pluginType]; var exportedMethods = new AssemblyParser(wrapperType.Assembly).GetExportedMethods(); exportedMethods = exportedMethods.Where(_ => !methodsToRemoveFromWrapper.Contains(_.ExportName)).ToArray(); var wrapper = GetMsilFile(wrapperType.Assembly.Location, cache: false, il => il .Replace("[TcPluginBase]TcPluginBase.PluginClassPlaceholder", $"[{pluginAssemblyName}]{pluginClass}") .Replace("[TcPluginBase]", "") ); var dllExportAttribute = $".custom instance void {typeof(DllExportAttribute).FullName}"; var count = 1; foreach (var method in wrapper.Classes.SelectMany(_ => _.Methods).Where(_ => _.Public && _.Static)) { var index = method.Lines.ToList().FindIndex(_ => _.ToString().Contains(dllExportAttribute)); if (index != -1) { var exportName = exportedMethods.FirstOrDefault(x => x.Method == method.Name).ExportName; if (!string.IsNullOrEmpty(exportName)) { method.Lines[index] = $".export [{count++}] as '{exportName}'"; } } } return(wrapper); }
internal (PluginType PluginType, string[] ExcludedMethods, string pluginClass, AssemblyName pluginAssemblyName) AnalyzeAssembly(FileInfo assemblyFile) { AppDomain.CurrentDomain.AssemblyResolve += new RelativeAssemblyResolver(assemblyFile.FullName).AssemblyResolve; var assembly = Assembly.LoadFile(assemblyFile.FullName); var parser = new AssemblyParser(assembly); var implementations = parser.GetImplementations(); // get excluded var excludedMethods = new List <string>(); foreach (var implementation in implementations) { var pluginType = implementation.Key; var pluginClasses = implementation.Value; if (pluginClasses.Length > 1) { throw new Exception($"Too many {pluginType} Plugin implementations in one project!! Found implementations in: {string.Join(", ", pluginClasses.Select(_ => _.FullName))}"); } excludedMethods.AddRange(parser.GetExcludedMethods(pluginClasses[0], pluginType)); } // check pluginType Type pluginClass; var pluginTypes = implementations.Select(_ => _.Key).ToArray(); switch (pluginTypes.Length) { case 0: throw new Exception("No Plugin implementation found!!"); case 1: // this is valid pluginClass = implementations.FirstOrDefault().Value.Single(); if (pluginTypes[0] == PluginType.FileSystem) { // exclude ContentPlugin methods from FileSystem plugin excludedMethods.AddRange(parser.GetExcludedMethods(null, PluginType.Content)); } break; case 2 when pluginTypes.Contains(PluginType.FileSystem) && pluginTypes.Contains(PluginType.Content): pluginTypes = new[] { PluginType.FileSystem }; pluginClass = implementations.FirstOrDefault(_ => _.Key == PluginType.FileSystem).Value.Single(); break; default: throw new Exception("Too Many or invalid combination of Plugin implementations found!!"); } var plgType = pluginTypes[0]; return(plgType, excludedMethods.Distinct().ToArray(), pluginClass.FullName, pluginClass.Assembly.GetName()); }