此时我正在轻松地将内容注入我的控制器中,在某些情况下构建我自己的ResolverServices类。 生活是美好的。
我无法弄清楚如何做到让框架自动注入非控制器类。框架自动注入我的控制器IOptions
的工作是什么,这实际上是我项目的配置:
public class MessageCenterController : Controller
{
private readonly MyOptions _options;
public MessageCenterController(IOptions<MyOptions> options)
{
_options = options.Value;
}
}
我认为我可以为自己的班级做同样的事情,我认为当我模仿控制器时,我很接近,就像这样:
public class MyHelper
{
private readonly ProfileOptions _options;
public MyHelper(IOptions<ProfileOptions> options)
{
_options = options.Value;
}
public bool CheckIt()
{
return _options.SomeBoolValue;
}
}
我认为我失败的地方就是我这样称呼它:
public void DoSomething()
{
var helper = new MyHelper(??????);
if (helper.CheckIt())
{
// Do Something
}
}
我跟踪此问题的几乎所有关于DI的内容都是在控制器级别讨论它。我尝试在Controller
对象源代码中搜索它发生的位置,但它在那里变得有点疯狂。
我知道我可以手动创建IOptions实例并将其传递给MyHelper
构造函数,但似乎我应该能够让框架执行此操作,因为它适用于Controllers
。
感谢您的帮助。
答案 0 :(得分:22)
以下是使用DI而没有涉及MVC控制器的任何内容的工作示例。这是我理解这个过程所需要做的事情,所以也许它会帮助别人。
ShoppingCart对象通过DI获取一个INotifier实例(通知客户他们的订单。)
atexit.register
答案 1 :(得分:18)
我们假设MyHelper
由MyService
使用,而MyService
则由您的控制人使用。
解决这种情况的方法是:
Register MyHelper
中的Startup.ConfigureServices
和services.AddTransient<MyService>();
services.AddTransient<MyHelper>();
。
MyService
控制器在其构造函数中接收public HomeController(MyService service) { ... }
的实例。
MyService
MyHelper
构造函数将依次接收public MyService(MyHelper helper) { ... }
的实例。
IServiceProvider
DI框架将能够毫无问题地解析整个对象图。如果您担心每次解析对象时都会创建新实例,那么您可以阅读不同的lifetime and registration options,例如单身或请求生命周期。
当您认为必须手动创建某项服务的实例时,您应该非常怀疑,因为您最终可能会进入service locator anti-pattern。最好将对象创建到DI容器。如果您确实发现自己处于这种情况(假设您创建了一个抽象工厂),那么您可以直接使用IServiceProvider
(在构造函数中请求var foo = serviceProvider.GetRequiredService<MyHelper>();
或使用{{1}} { {3}})。
{{1}}
我建议阅读有关ASP.Net 5 DI框架的特定exposed in the httpContext以及一般的依赖注入。
答案 2 :(得分:5)
不幸的是没有直接的方法。我设法使其工作的唯一方法是创建一个静态类并在其他地方使用它,如下所示:
public static class SiteUtils
{
public static string AppName { get; set; }
public static string strConnection { get; set; }
}
然后在你的启动课程中,填写如下:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
//normal as detauls , removed for space
// set my variables all over the site
SiteUtils.strConnection = Configuration.GetConnectionString("DefaultConnection");
SiteUtils.AppName = Configuration.GetValue<string>("AppName");
}
虽然这是一个糟糕的模式,因为这将保留应用程序的整个生命周期,我找不到更好的方法在控制器外使用它。
答案 3 :(得分:2)
基于当前的.NET Core 2.2 DI文档here,这是一个更完整的示例,可以直接回答OP的问题。添加此答案,因为它可能会对.NET Core DI的新手有所帮助,并且因为该问题是Google的顶级搜索结果。
首先,为MyHelper添加一个接口:
public interface IMyHelper
{
bool CheckIt();
}
第二,更新MyHelper类以实现该接口(在Visual Studio中,按ctrl-。以实现该接口):
public class MyHelper : IMyHelper
{
private readonly ProfileOptions _options;
public MyHelper(IOptions<ProfileOptions> options)
{
_options = options.Value;
{
public bool CheckIt()
{
return _options.SomeBoolValue;
}
}
第三,在DI服务容器中将接口注册为框架提供的服务。为此,请在Startup.cs的ConfigureServices方法中以具体类型MyHelper注册IMyHelper服务。
public void ConfigureServices(IServiceCollection services)
{
...
services.AddScoped<IMyHelper, MyHelper>();
...
}
第四,创建一个私有变量以引用服务实例。将服务作为构造函数中的参数传递(通过构造函数注入),然后使用服务实例初始化变量。通过私有变量引用此自定义类实例的任何属性或调用方法。
public class MessageCenterController : Controller
{
private readonly MyOptions _options;
private readonly IMyHelper _myHelper;
public MessageCenterController(
IOptions<MyOptions> options,
IMyHelper myHelper
)
{
_options = options.value;
_myHelper = myHelper;
}
public void DoSomething()
{
if (_myHelper.CheckIt())
{
// Do Something
}
}
}
答案 4 :(得分:0)
您可以使用Activator.CreateInstance()。这是一个包装函数。使用方法如下。
var definedProgrammatically =“ My.NameSpace.DemoClass1”; //实现IDemo接口
var obj = CreateInstance
现在,您有一个obj实例,该实例从以编程方式确定的类型实例化。可以将该obj注入非控制器类中。
public TInterface CreateInstance<TInterface, TParameter>(string typeName, TParameter constructorParam, string dllName = null)
{
var type = dllName == null ? System.Type.GetType(typeName) :
System.AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a => a.FullName.StartsWith(dllName, System.StringComparison.OrdinalIgnoreCase)).GetType(typeName);
return (TInterface)System.Activator.CreateInstance(type, constructorParam);
}
PS:您可以遍历System.AppDomain.CurrentDomain.GetAssemblies()以确定容纳您的类的程序集的名称。该名称在包装函数的第3个参数中使用。