我正在构建一个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
我正在加载装配:(灵感:How to load assemblies located in a folder in .net core console app)
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<IFoo,Foo>();
它应该在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; } } }