如何在dotnet核心中动态加载程序集
我正在构建一个Web应用程序,我想要单独关注,即在不同的项目中进行抽象和实现。
为了实现这一点,我尝试实现一个组合根概念,其中所有实现必须有一个ICompositionRootComposer
实例来注册服务,类型等。
public interface ICompositionRootComposer { void Compose(ICompositionConfigurator configurator); }
在构建层次结构中直接引用的项目中,将调用ICompositionRootComposer
实现,并在基础IoC容器中正确注册服务。
当我尝试在项目中注册服务时出现问题,我在其中设置了一个后期构建任务,将构建的dll复制到Web项目的调试文件夹:
cp -R $(TargetDir)"assembly and symbol name"* $(SolutionDir)src/"webproject path"/bin/Debug/netcoreapp1.1
我正在加载程序集:(灵感: 如何在.net核心控制台应用程序中加载位于文件夹中的程序集 )
internal class AssemblyLoader : AssemblyLoadContext { private string folderPath; internal AssemblyLoader(string folderPath) { this.folderPath = Path.GetDirectoryName(folderPath); } internal Assembly Load(string filePath) { FileInfo fileInfo = new FileInfo(filePath); AssemblyName assemblyName = new AssemblyName(fileInfo.Name.Replace(fileInfo.Extension, string.Empty)); return this.Load(assemblyName); } protected override Assembly Load(AssemblyName assemblyName) { var dependencyContext = DependencyContext.Default; var ressource = dependencyContext.CompileLibraries.FirstOrDefault(r => r.Name.Contains(assemblyName.Name)); if(ressource != null) { return Assembly.Load(new AssemblyName(ressource.Name)); } var fileInfo = this.LoadFileInfo(assemblyName.Name); if(File.Exists(fileInfo.FullName)) { Assembly assembly = null; if(this.TryGetAssemblyFromAssemblyName(assemblyName, out assembly)) { return assembly; } return this.LoadFromAssemblyPath(fileInfo.FullName); } return Assembly.Load(assemblyName); } private FileInfo LoadFileInfo(string assemblyName) { string fullPath = Path.Combine(this.folderPath, $"{assemblyName}.dll"); return new FileInfo(fullPath); } private bool TryGetAssemblyFromAssemblyName(AssemblyName assemblyName, out Assembly assembly) { try { assembly = Default.LoadFromAssemblyName(assemblyName); return true; } catch { assembly = null; return false; } } }
有了这个,我就可以加载程序集并调用项目ICompositionRootComposer
实现。
但问题是它似乎没有认出我的任何类型。
用来调用我的配置器时
configurator.RegisterTransiantService();
它应该在IoC中注册IFoo和Foo。
但是在调试时我无法获取类型的信息,即通过Visual Studio Code中调试控制台中的typeof(Foo)。
Necromancing。
您可以为旧的Assembly.LoadFile创建一个包装类来执行此操作。
这样做的另一个好处是,您可以通过在旧代码库中应用搜索和替换更改来保持与dotnet-none-core的向后兼容。
您需要通过nuget添加System.Runtime.Loader
。
namespace System.Reflection { public class Assembly2 { public static System.Reflection.Assembly LoadFile(string path) { System.Reflection.Assembly ass = null; #if NET_CORE // Requires nuget - System.Runtime.Loader ass = System.Runtime.Loader.AssemblyLoadContext.Default .LoadFromAssemblyPath(path); #else ass = System.Reflection. Assembly.LoadFile(path); #endif // System.Type myType = ass.GetType("Custom.Thing.SampleClass"); // object myInstance = Activator.CreateInstance(myType); return ass; } } }
我找到了解决问题的方法。
事实certificate,我将属性PreserveCompilationContext
设置为true,这就是调试器不会注册我手动复制的程序集的原因。 当我从web项目csproj文件中删除属性时,一切正常。
您是否知道ASP.NET Core拥有自己的内置dependency injection机制? 它可以根据您的需要轻松切换到其他IoC容器,我认为您不需要重新发明它。
你需要做的是使用reflection来制作generics方法并在此之后调用,如下所示:
上述就是C#学习教程:如何在dotnet核心中动态加载程序集分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
public void ConfigureServices(IServiceCollection services) { var myAssembly = LoadAssembly(); // find first interface var firstInterfaceType = myAssembly.DefinedTypes.FirstOrDefault(t => t.IsInterface).GetType(); // find it's implementation var firstInterfaceImplementationType = myAssembly.DefinedTypes.Where(t => t.ImplementedInterfaces.Contains(firstInterfaceType)).GetType(); // get general method info MethodInfo method = typeof(IServiceCollection).GetMethod("AddTransient"); // provide types to generic method MethodInfo generic = method.MakeGenericMethod(firstInterfaceType, firstInterfaceImplementationType); // register your types generic.Invoke(services, null); }
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/954856.html