如何在SimpleInjector注入的类库构造函数中获取主程序集名称?
在类库构造函数中获取WCF主服务程序集名称的解决方案
我之前也碰到过一模一样的场景:用SimpleInjector把MySolution.MyLibrary注册到MySolution.MyService这个WCF服务里做单例,结果在类库构造函数里拿主服务程序集名称时踩了和你一样的坑。下面给你几个靠谱的解决办法:
方法一:依赖注入传递(最推荐)
既然用了DI容器,最符合设计原则的方式就是由服务端主动把主程序集信息传给类库,而不是让类库自己去“找”。
在MySolution.MyService的DI注册代码里,先拿到当前服务的程序集,再注册成实例:
// 服务端的DI注册代码 var hostAssembly = Assembly.GetExecutingAssembly(); container.RegisterInstance(hostAssembly); container.Register<IMyLibrary, MyLibrary>(Lifestyle.Singleton);
然后修改MyLibrary的构造函数,接收这个Assembly参数:
public class MyLibrary : IMyLibrary { public MyLibrary(Assembly hostAssembly) { string hostAssemblyName = hostAssembly.GetName().FullName; // 这里就拿到MySolution.MyService的完整程序集名称了 } }
这种方法完全避免了类库对宿主环境的依赖,不管以后宿主换成控制台、ASP.NET还是其他,只要注入对应的程序集就行,非常灵活。
方法二:遍历AppDomain加载的程序集
如果不想修改DI注册逻辑,可以遍历当前AppDomain里所有已加载的程序集,筛选出你要的那个:
public class MyLibrary : IMyLibrary { public MyLibrary() { var hostAssembly = AppDomain.CurrentDomain.GetAssemblies() .FirstOrDefault(a => a.GetName().Name.Equals("MySolution.MyService", StringComparison.OrdinalIgnoreCase)); if (hostAssembly != null) { string hostAssemblyName = hostAssembly.GetName().FullName; // 处理你的业务逻辑 } } }
这里用Name而非FullName匹配,是为了避免版本号、公钥令牌等信息变化导致匹配失败。不过这种方法有个小局限:如果环境里有同名程序集加载进来,可能会拿到错误的那个,适合你能确保只有一个MySolution.MyService程序集的场景。
为什么你之前的方法行不通?
顺便给你解释下踩坑的原因:
Assembly.GetExecutingAssembly():这个方法返回的是当前代码所在的程序集,也就是MySolution.MyLibrary本身,所以肯定拿不到服务程序集的名称。Assembly.GetCallingAssembly():SimpleInjector创建实例时用到了动态方法生成(DynamicMethods),调用栈里的调用方变成了匿名动态程序集,自然返回的不是服务程序集。Assembly.GetEntryAssembly():WCF服务是由IIS或WCF宿主进程(比如w3wp.exe)托管的,对于托管类库来说,入口程序集是宿主进程而非你的MySolution.MyService,所以返回null是正常的。
内容的提问来源于stack exchange,提问作者dstr
相关产品推荐
相关产品推荐

