[英]Dependency Injection and Configurations - .NET Core
Creating a standalone project which read JSON and simply response back.创建一个读取 JSON 的独立项目并简单地回复。 Trying to make the best use of dependency injection.试图充分利用依赖注入。 However, I've few questions to clarify.但是,我有几个问题需要澄清。
So firstly HomeController
is called which has a dependendency on ClassA
, so after refactoring ClassA
implements IClassA
and Updating Startup.cs
, HomeController
can now successfully use the instance created by the Startup.cs to invoke the method _IClassA.GetOP(data)
.所以首先调用了依赖于ClassA
的HomeController
,因此在重构ClassA
实现IClassA
并更新Startup.cs
之后, HomeController
现在可以成功地使用 Startup.cs 创建的实例来调用方法_IClassA.GetOP(data)
。
Now I see similar behavior where ClassA
has a dependency on ClassB
, UtiClass
& Document
class.现在我看到ClassA
依赖于ClassB
、 UtiClass
和Document
class 的类似行为。 So do I need to create Interfaces for all to remove the new
keyword used for creating instances.所以我需要为所有人创建接口以删除用于创建实例的new
关键字。
Again, my primary focus is to retrieve the value of KeysAndValues
-> path
.同样,我的主要重点是检索KeysAndValues
-> path
的值。 So in ClassA
constructor I instantiated ClassB
and pass the IOptions<KeyAndValue>
.因此,在ClassA
构造函数中,我实例化了ClassB
并传递了IOptions<KeyAndValue>
。 Unfortunately, I am unable to get the value of options.path
.不幸的是,我无法获得options.path
的值。 Please help to clarify my doubts and kindly solve this puzzle.请帮助澄清我的疑问并解决这个难题。 Thank you.谢谢你。
//HomeController
public class HomeController : ControllerBase
{
private readonly IClassA _IClassA;
public HomeController(IClassA iClassA)
_IClassA = iClassA;
public string Get(DTO_A data)
var result = _IClassA.GetOP(data);
}
//INTERFACE
public interface IClassA
public string GetOP(DTO_A data);
//Class
public sealed class ClassA : IClassA
//private readonly IClassB _IClassB; //Cannot Instantiated
private readonly ClassB _ClassB;
public ClassA(IOptions<KeysAndValues> options)
_ClassB = new ClassB(options);
Document request = new Document();
UtiClass objUtiClass = new UtiClass();
public string GetOP(DTO_A data)
{
request.Name = data.Name;
objUtiClass .Document = request;
_ClassB.UpdateMethod(objUtiClass );
}
public class Document : IDocument
{}
public class ClassC
{}
Startup.cs启动.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<IClassA, ClassA>();
services.AddControllers();
services.AddScoped<IClassB, ClassB>();
services.Configure<KeysAndValues>(Configuration.GetSection("KeysAndValues"));
}
public class ClassB : IClassB
private IOptions<KeysAndValues> options;
public ClassB(IOptions<KeysAndValues> options)
this.options = options;
public void UpdateMethod(UtiClass req)
string fille = Path.Combine(options.path);
}
public class KeysAndValues
public string path { get; set; }
Just like how class HomeController
requires interface IClassA
, class ClassA
needs to require interface IClassB
.就像 class HomeController
需要接口IClassA
, class ClassA
需要接口IClassB
。 Class ClassB
is the one that requires IOptions<KeysAndValues>
, because it's ClassB
that actually needs the path
value. Class ClassB
是需要IOptions<KeysAndValues>
的,因为实际上需要path
值的是ClassB
。
Now, you don't need to use interfaces at all here.现在,您根本不需要在这里使用接口。 However, I'd recommend using interfaces because it makes your life much easier should you add unit testing.但是,我建议使用接口,因为如果您添加单元测试,它会让您的生活更轻松。
Here's what it would look like with interfaces.这是接口的样子。
public class HomeController : ControllerBase
{
private readonly IClassA _IClassA;
public HomeController(IClassA iClassA)
{
_IClassA = iClassA;
}
}
public interface IClassA { }
public interface IClassB { }
public class ClassA : IClassA
{
private readonly IClassB _IClassB;
public ClassA(IClassB iClassB)
{
_IClassB = iClassB;
}
}
public class ClassB : IClassB
{
private readonly KeysAndValues options;
public ClassB(IOptions<KeysAndValues> options)
{
this.options = options.Value;
}
}
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddTransient<IClassA, ClassA>();
services.AddTransient<IClassB, ClassB>();
services.Configure<KeysAndValues>(Configuration.GetSection("KeysAndValues"));
}
If you don't want to use interface, just remove all the interfaces and replace all constructor parameters with the concrete class, and modify ConfigureServices
with如果您不想使用接口,只需删除所有接口并将所有构造函数参数替换为具体的 class,并将ConfigureServices
修改为
services.AddTransient<ClassA>();
services.AddTransient<ClassB>();
I'd recommend AddTransient
over AddScoped
.我会推荐AddTransient
而不是AddScoped
。 Use Scoped only if you need information from the HTTP request/response explicitly in that service.仅当您需要来自该服务中明确的 HTTP 请求/响应的信息时,才使用 Scoped。 I'd also recommend not having any properties in a service ( Document request
and UtiClass objUtiClass
) that are not readonly
and set by DI, or you'll need to use AddSingleton
and ensure you don't get race conditions (which your current code looks like it will).我还建议不要在服务( Document request
和UtiClass objUtiClass
)中包含任何不是readonly
且由 DI 设置的属性,否则您将需要使用AddSingleton
并确保您不会遇到竞争条件(您当前的代码看起来会的)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.