目前在学习ASP.NET CORE MVC中,今天看到微软在ASP.NET CORE MVC 2.0中又恢复了允许开发人员引用第三方DLL程序集的功能,感到甚是高兴!于是我急忙写了个Demo想试试,我的项目结构如下:

可以看到解决方案中就两个项目,AspNetCoreWebApp就是一个ASP.NET CORE MVC 2.0的项目,而MyNetCoreLib是一个.Net Core 2.0的类库项目,为了体现AspNetCoreWebApp是通过程序集来引用MyNetCoreLib的,我还在解决方案中创建了一个文件夹叫Reference,将类库项目MyNetCoreLib编译后生成的DLL文件放到了Reference文件夹中,然后在AspNetCoreWebApp中通过添加引用程序集的方式引用了MyNetCoreLib.dll,如下图所示:

然后编译整个解决方案,调试AspNetCoreWebApp这个项目,运行立马报错。。。错误如下:

这明显是一个运行时错误,因我在编译整个解决方案的时候是成功的,没有报任何错误。后来去网上查了查资料,发现虽然我们在项目AspNetCoreWebApp中引用了MyNetCoreLib.dll,而且项目AspNetCoreWebApp编译后也在其Bin目录下输出了MyNetCoreLib.dll这个文件,如下图所示:

但是ASP.NET CORE MVC的依赖注入环境其实并不知道该到哪里去找MyNetCoreLib.dll这个文件,所以才会在运行时报出InvalidOperationException: Cannot find compilation library location for package 'MyNetCoreLib'这种错误。。。开发人员需要用代码去告诉ASP.NET CORE MVC应该到哪里去找到MyNetCoreLib.dll这个文件。

因此首先我们需要定义一个叫MetadataReferenceFeatureProvider的类,代码如下,其关键代码就是告诉ASP.NET CORE MVC的依赖注入环境去AppDomain.CurrentDomain.BaseDirectory(也就是Bin目录)下找我们在项目中引用的程序集文件

using Microsoft.AspNetCore.Mvc.ApplicationParts;
using Microsoft.AspNetCore.Mvc.Razor.Compilation;
using Microsoft.CodeAnalysis;
using Microsoft.Extensions.DependencyModel;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection.PortableExecutable;
using System.Threading.Tasks; namespace AspNetCoreWebApp.Utils
{
public class ReferencesMetadataReferenceFeatureProvider : IApplicationFeatureProvider<MetadataReferenceFeature>
{
public void PopulateFeature(IEnumerable<ApplicationPart> parts, MetadataReferenceFeature feature)
{
var libraryPaths = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
foreach (var assemblyPart in parts.OfType<AssemblyPart>())
{
var dependencyContext = DependencyContext.Load(assemblyPart.Assembly);
if (dependencyContext != null)
{
foreach (var library in dependencyContext.CompileLibraries)
{
if (string.Equals("reference", library.Type, StringComparison.OrdinalIgnoreCase))
{
foreach (var libraryAssembly in library.Assemblies)
{
//告诉ASP.NET CORE MVC如果现在项目中有引用第三方程序集,要到AppDomain.CurrentDomain.BaseDirectory这个文件夹(就是Bin目录)下去寻找该程序集的dll文件
libraryPaths.Add(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, libraryAssembly));
}
}
else
{
foreach (var path in library.ResolveReferencePaths())
{
libraryPaths.Add(path);
}
}
}
}
else
{
libraryPaths.Add(assemblyPart.Assembly.Location);
}
} foreach (var path in libraryPaths)
{
feature.MetadataReferences.Add(CreateMetadataReference(path));
}
} private static MetadataReference CreateMetadataReference(string path)
{
using (var stream = File.OpenRead(path))
{
var moduleMetadata = ModuleMetadata.CreateFromStream(stream, PEStreamOptions.PrefetchMetadata);
var assemblyMetadata = AssemblyMetadata.Create(moduleMetadata); return assemblyMetadata.GetReference(filePath: path);
}
} }
}

其次我们还要在项目AspNetCoreWebApp的Startup.cs文件中的services.AddMvc()方法上注册我们定义的这个Provider,代码如下(注意ConfigureServices方法中的代码):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Mvc.Razor.Compilation;
using AspNetCoreWebApp.Utils; namespace AspNetCoreWebApp
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
} public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().ConfigureApplicationPartManager(manager =>
{
//移除ASP.NET CORE MVC管理器中默认内置的MetadataReferenceFeatureProvider,该Provider如果不移除,还是会引发InvalidOperationException: Cannot find compilation library location for package 'MyNetCoreLib'这个错误
manager.FeatureProviders.Remove(manager.FeatureProviders.First(f => f is MetadataReferenceFeatureProvider));
//注册我们定义的ReferencesMetadataReferenceFeatureProvider到ASP.NET CORE MVC管理器来代替上面移除的MetadataReferenceFeatureProvider
manager.FeatureProviders.Add(new ReferencesMetadataReferenceFeatureProvider());
});
} // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseBrowserLink();
}
else
{
app.UseExceptionHandler("/Home/Error");
} app.UseStaticFiles(); app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
}
}

然后重新编译代码,调试项目AspNetCoreWebApp,好了这下项目成功运行了,没有报任何错误。

也不知道本文讨论的这个问题是ASP.NET CORE MVC 2.0的一个缺陷,会在以后版本中修复,还是微软故意为之?因为我试了下在.NET CORE 2.0的控制台项目中,直接引用第三方程序集DLL文件是完全没问题的,不需要写任何额外的代码就可以使用。既然微软在ASP.NET CORE MVC中也开放了引用第三方程序集这个功能,其实就完全可以把它做的和老.Net Framework一样,自动去Bin目录下面寻找DLL文件即可,希望ASP.NET CORE MVC以后的版本能够完善这个功能,不再需要开发人员在引用DLL文件后,还要添加额外的代码。

ASP.NET CORE MVC 2.0 项目中引用第三方DLL报错的解决办法 - InvalidOperationException: Cannot find compilation library location for package的更多相关文章

  1. .ner core InvalidOperationException: Cannot find compilation library location for package 'xxx' 和 SqlException: 'OFFSET' 附近有语法错误。 在 FETCH 语句中选项 NEXT 的用法无效。问题

    原文地址:传送门 1.InvalidOperationException: Cannot find compilation library location for package 'xxx'问题: ...

  2. eclipse中的js文件报错的解决办法

    在使用别人的项目的时候,导入到eclipse中发现js文件报错,解决办法是关闭eclipse的js校验功能. 三个步骤: 1. 右键点击项目->properties->Validation ...

  3. 关于pycharm中安装第三方库时报错的解决办法(一)

    记录自己的生活!   一.事发背景 在pycharm中直接安装第三方库时因为版本问题总是无法安装成功,事情不大,但是很重要.   二.经过 最开始我自己电脑上安装了Python3.6和Python2. ...

  4. vue-cli创建的项目中引入第三方库报错 'caller', 'calle', and 'arguments' properties may not be...

    http://blog.csdn.net/sophie_u/article/details/76223978 以在vue中引入mui第三方库为例: 虽然针对vue,有单独的vue-mui库可以使用,但 ...

  5. vue-cli创建的项目中引入第三方库报错'caller', 'calle', and 'arguments' properties may not be...

    本文链接:https://blog.csdn.net/Sophie_U/article/details/76223978 问题: 在vue的main.js中引入mui.min.js时,报错. 如上,单 ...

  6. 【转】】Vue项目部署tomcat,刷新报错404解决办法

    转自[https://blog.csdn.net/g631521612/article/details/82835518] 解决方式: - 在tocmat的webapps下的项目中创建WEB-INF文 ...

  7. Eclipse安卓项目导入android.support.design报错的解决办法

    导入android.support.design出错:1.项目除了需要依赖appcompat_v7包外还要design包2.design包就是在安卓sdk下Extras中的android.suppor ...

  8. ASP.NET MVC 返回JsonResult序列化内容超出最大限制报错的解决办法

    在使用MVC的时候我们经常会在Controller的Action方法中返回JsonResult对象,但是有时候你如果序列化的对象太大会导致JsonResult从Controller的Action返回后 ...

  9. PyCharm注释中出现中文运行报错的解决办法

    SyntaxError: Non-UTF-8 code starting with '..... 方法一:在文件首行加上 # -*- coding:utf-8 -*- 方法二:更改编码格式 File ...

随机推荐

  1. sql server 2012 新知识-序列

    今天聊一聊sql 2012 上的新功能-----序列 按我的理解,它就是为了实现全局性的唯一标识,按sql server 以前的版本,想对一张表标识很简单,比如identity,但如果要对某几张有业务 ...

  2. java基础->循环

    while循环 格式:   while(条件表达式) { // 条件表达式其实就是一个结果为boolean类型的代码 循环体; } 执行流程: 先判断条件表达式的值, 如果为true就执行循环体,执行 ...

  3. MySQL 数据类型和约束(外键是重点🙄)

    数据类型 1. 数字(默认都是由符号,宽度表示的是显示宽度,与存储无关).tinyint 括号里指定宽度 七位2进制数最大数就是2**7 -1=127 最小是-128 验证: create tabel ...

  4. sqlalchemy 踩过的坑

    记录下Sqlalchemy遇到的问题,不定时更新. 设置主键为非自增 sqlalchemy 在sql server中默认主键是自增的,如果在数据库设置的主键不是自增的,这个时候插入就会出现异常: 提示 ...

  5. git强制push

    Git 如何强制push? $ git push -u origin master –f   文章来源:刘俊涛的博客 地址:http://www.cnblogs.com/lovebing 欢迎关注,有 ...

  6. 微信小程序开发之详解生命周期方法

    生命周期是指一个小程序从创建到销毁的一系列过程 在小程序中 ,通过App()来注册一个小程序 ,通过Page()来注册一个页面 先来看一张小程序项目结构 从上图可以看出,根目录下面有包含了app.js ...

  7. SQL Server 禁用扩展存储过程

    概述 扩展存储过程是 SQL Server 实例可以动态加载和运行的 DLL.扩展存储过程是使用 SQL Server 扩展存储过程 API 编写的,可直接在 SQL Server 实例的地址空间中运 ...

  8. Java学习笔记18---final关键字修饰变量、方法及类

    英语里final这个单词大家都知道是"最终的"意思,其实还有一个意思是"不可更改的".在Java里,final关键字作"不可更改的"来解释更 ...

  9. Linux下用ls和du命令查看文件以及文件夹大小

    ls的用法 ls -l |grep "^-"|wc -l或find ./company -type f | wc -l  查看某文件夹下文件的个数,包括子文件夹里的. ls -lR ...

  10. IIS发布 用户 \'IIS APPPOOL\\X\' 登录失败

    曾多次遇到这个问题,我的解决方案就是修改数据库连接字符串 网上给的解决方案就是更换应用程序池的"进程模型":参考:http://jingyan.baidu.com/album/20 ...