我对 ASP.NET 5 (vNext) 中的一些概念感到困惑。
其中之一是用于配置的依赖注入(inject)方法。好像我必须通过堆栈一直传递一个参数。我可能误解了什么或做错了。
假设我有一个名为“contactEmailAddress”的配置属性。当下新订单时,我将使用该配置属性发送电子邮件。考虑到这种情况,我的 ASP.NET 5 堆栈将如下所示:
Startup.cs
public class Startup
{
public IConfiguration Configuration { get; set; }
public Startup(IHostingEnvironment environment)
{
var configuration = new Configuration().AddJsonFile("config.json");
Configuration = configuration;
}
public void ConfigureServices(IServiceCollection services)
{
services.Configure<AppSettings>(Configuration.GetSubKey("AppSettings"));
services.AddMvc();
}
public void Configure(IApplicationBuilder app)
{
app.UseErrorPage();
app.UseMvc(routes =>
{
routes.MapRoute("default",
"{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index" });
}
);
app.UseWelcomePage();
}
AppSettings.cs
public class AppSettings
{
public string ContactEmailAddress { get; set; }
}
config.json
{
"AppSettings": {
"ContactEmailAddress":"support@mycompany.com"
}
}
OrderController.cs
[Route("orders")]
public class OrdersController : Controller
{
private IOptions<AppSettings> AppSettings { get; set; }
public OrdersController(IOptions<AppSettings> appSettings)
{
AppSettings = appSettings;
}
[HttpGet("new-order")]
public IActionResult OrderCreate()
{
var viewModel = new OrderViewModel();
return View(viewModel);
}
[HttpPost("new-order")]
public IActionResult OrderCreate(OrderViewModel viewModel)
{
return new HttpStatusCodeResult(200);
}
}
Order.cs
public class Order()
{
public void Save(IOptions<AppSettings> appSettings)
{
// Send email to address in appSettings
}
public static List<Order> FindAll(IOptions<AppSettings> appSettings)
{
// Send report email to address in appSettings
return new List<Order>();
}
}
如上例所示,我将 AppSettings 传递给整个堆栈。这感觉不对。更让我担心的是,如果我尝试使用需要访问配置设置的第三方库,这种方法将不起作用。第三方库如何访问配置设置?我误会了什么吗?有更好的方法吗?
最佳答案
您正在纠缠 2 个不同的运行时资源提供程序,AppSettings 和 Dependency Injection。
AppSettings,提供对应用程序特定值(如 UICulture 字符串、联系电子邮件等)的运行时访问。
DI 容器 是管理服务访问及其生命周期范围的工厂。例如,如果 MVC Controller 需要访问您的 EmailService,您可以配置
public void ConfigureServices(IServiceCollection services)
{
// Add all dependencies needed by Mvc.
services.AddMvc();
// Add EmailService to the collection. When an instance is needed,
// the framework injects this instance to the objects that needs it
services.AddSingleton<IEmailService, EmailService>();
}
然后,如果我们的 Home Controller 需要访问您的 EmailService,我们通过将其作为参数添加到 Controller 构造函数来添加对其接口(interface)的依赖
public class HomeController : Controller
{
private readonly IEmailService _emailService;
private readonly string _emailContact;
/// The framework will inject an instance of an IEmailService implementation.
public HomeController(IEmailService emailService)
{
_emailService = emailService;
_emailContact = System.Configuration.ConfigurationManager.
AppSettings.Get("ContactEmail");
}
[HttpPost]
public void EmailSupport([FromBody] string message)
{
if (!ModelState.IsValid)
{
Context.Response.StatusCode = 400;
}
else
{
_emailService.Send(_emailContact, message);
依赖注入(inject)的目的是管理服务的访问和生命周期。
在前面的示例中,在我们的应用程序 Startup 中,我们将 DI 工厂配置为将 IEmailService 的应用程序请求与 EmailService 相关联。因此,当我们的 Controller 由 MVC 框架 实例化时,框架注意到我们的 Home Controller 需要 IEmailService,框架检查我们的应用程序服务集合。它找到映射指令并将 Singleton EmailService(占用接口(interface)的后代)注入(inject)到我们的家庭 Controller 中。
super 多态因子 - 可恶!
为什么这很重要?
如果您的联系电子邮件发生变化,您可以更改 AppSetting 值并完成。 ConfigurationManager 对“ContactEmail”的所有请求都已全局更改。字符串很容易。当我们可以散列时不需要注入(inject)。
如果您的存储库、电子邮件服务、日志服务等发生变化,您需要一种全局方式来更改对该服务的所有引用。服务引用不像不可变字符串文字那样容易传输。服务实例化应由工厂处理以配置服务的设置和依赖项。
因此,在一年内您开发了一个 RobustMailService:
Class RobustMailService : IEmailService
{
....
}
只要您的新 RobustMailService 继承并实现了 IEmailService 接口(interface),您就可以通过更改全局替换对邮件服务的所有引用:
public void ConfigureServices(IServiceCollection services)
{
// Add all dependencies needed by Mvc.
services.AddMvc();
// Add RobustMailService to the collection. When an instance is needed,
// the framework injects this instance to the objects that needs it
services.AddSingleton<IEmailService, RobustMailService>();
}
关于c# - 在 ASP.NET 5 (vNext) 中获取配置值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30443133/
作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代
是的,我知道最好使用webmock,但我想知道如何在RSpec中模拟此方法:defmethod_to_testurl=URI.parseurireq=Net::HTTP::Post.newurl.pathres=Net::HTTP.start(url.host,url.port)do|http|http.requestreq,foo:1endresend这是RSpec:let(:uri){'http://example.com'}specify'HTTPcall'dohttp=mock:httpNet::HTTP.stub!(:start).and_yieldhttphttp.shou
我有一个在Linux服务器上运行的ruby脚本。它不使用rails或任何东西。它基本上是一个命令行ruby脚本,可以像这样传递参数:./ruby_script.rbarg1arg2如何将参数抽象到配置文件(例如yaml文件或其他文件)中?您能否举例说明如何做到这一点?提前谢谢你。 最佳答案 首先,您可以运行一个写入YAML配置文件的独立脚本:require"yaml"File.write("path_to_yaml_file",[arg1,arg2].to_yaml)然后,在您的应用中阅读它:require"yaml"arg
我已经在Sinatra上创建了应用程序,它代表了一个简单的API。我想在生产和开发上进行部署。我想在部署时选择,是开发还是生产,一些方法的逻辑应该改变,这取决于部署类型。是否有任何想法,如何完成以及解决此问题的一些示例。例子:我有代码get'/api/test'doreturn"Itisdev"end但是在部署到生产环境之后我想在运行/api/test之后看到ItisPROD如何实现? 最佳答案 根据SinatraDocumentation:EnvironmentscanbesetthroughtheRACK_ENVenvironm
有没有办法在这个简单的get方法中添加超时选项?我正在使用法拉第3.3。Faraday.get(url)四处寻找,我只能先发起连接后应用超时选项,然后应用超时选项。或者有什么简单的方法?这就是我现在正在做的:conn=Faraday.newresponse=conn.getdo|req|req.urlurlreq.options.timeout=2#2secondsend 最佳答案 试试这个:conn=Faraday.newdo|conn|conn.options.timeout=20endresponse=conn.get(url
我有一个存储主机名的Ruby数组server_names。如果我打印出来,它看起来像这样:["hostname.abc.com","hostname2.abc.com","hostname3.abc.com"]相当标准。我想要做的是获取这些服务器的IP(可能将它们存储在另一个变量中)。看起来IPSocket类可以做到这一点,但我不确定如何使用IPSocket类遍历它。如果它只是尝试像这样打印出IP:server_names.eachdo|name|IPSocket::getaddress(name)pnameend它提示我没有提供服务器名称。这是语法问题还是我没有正确使用类?输出:ge
我想获取模块中定义的所有常量的值:moduleLettersA='apple'.freezeB='boy'.freezeendconstants给了我常量的名字:Letters.constants(false)#=>[:A,:B]如何获取它们的值的数组,即["apple","boy"]? 最佳答案 为了做到这一点,请使用mapLetters.constants(false).map&Letters.method(:const_get)这将返回["a","b"]第二种方式:Letters.constants(false).map{|c
我安装了ruby版本管理器,并将RVM安装的ruby实现设置为默认值,这样'哪个ruby'显示'~/.rvm/ruby-1.8.6-p383/bin/ruby'但是当我在emacs中打开inf-ruby缓冲区时,它使用安装在/usr/bin中的ruby。有没有办法让emacs像shell一样尊重ruby的路径?谢谢! 最佳答案 我创建了一个emacs扩展来将rvm集成到emacs中。如果您有兴趣,可以在这里获取:http://github.com/senny/rvm.el
如何在ruby中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL
假设我有这个范围:("aaaaa".."zzzzz")如何在不事先/每次生成整个项目的情况下从范围中获取第N个项目? 最佳答案 一种快速简便的方法:("aaaaa".."zzzzz").first(42).last#==>"aaabp"如果出于某种原因你不得不一遍又一遍地这样做,或者如果你需要避免为前N个元素构建中间数组,你可以这样写:moduleEnumerabledefskip(n)returnto_enum:skip,nunlessblock_given?each_with_indexdo|item,index|yieldit