In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-16 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
This article is about the sample analysis of basic configuration and dependency injection in the ABP framework. The editor thinks it is very practical, so share it with you as a reference and follow the editor to have a look.
Configure ABP
Configuration is achieved in the PreInitialize method of your own module
The code example is as follows:
Public class SimpleTaskSystemModule: AbpModule {public override void PreInitialize () {/ / add a language pack to your application, which is English and Turkish for the author. Configuration.Localization.Languages.Add (new LanguageInfo ("en", "English", "famfamfam-flag-england", true)); Configuration.Localization.Languages.Add (new LanguageInfo ("tr", "T ü rk ç e", "famfamfam-flag-tr"); Configuration.Localization.Sources.Add (new XmlLocalizationSource ("SimpleTaskSystem", HttpContext.Current.Server.MapPath ("~ / Localization/SimpleTaskSystem") / / configure navigation and menu Configuration.Navigation.Providers.Add ();} public override void Initialize () {IocManager.RegisterAssemblyByConvention (Assembly.GetExecutingAssembly ());}}
Similar to orchard, the abp framework is designed to be modular from the beginning, and different modules can be configured through the abp framework. For example, navigation can be added to different modules, and menu items can be added to the self-defined main menu through navigation. For details, please refer to:
Localization: http://www.aspnetboilerplate.com/Pages/Documents/Localization
Navigation: http://www.aspnetboilerplate.com/Pages/Documents/Navigation
Configuration module
How does abp differ from the native startup configuration of the. Net framework? The modules of the abp framework can be personalized extended through the IAbpModuleConfigurations interface, so that the module configuration is more simple and convenient.
The sample code is as follows:
... using Abp.Web.Configuration;...public override void PreInitialize () {Configuration.Modules.AbpWeb (). SendAllExceptionsToClients = true;}.
In the above example, we send exceptions to the client by configuring the AbpWeb module. Of course, not every module needs this configuration, and usually we do it when a module needs to be reused in many different applications.
Create a configuration for a module
The following code, if we have a module named MyModule, and this module has some of its own configuration. So first we need to create some classes that are defined as properties (translator's note: attributes have automatic get and set accessors. ), representing different configurations
Public class MyModuleConfig {public bool SampleConfig1 {get; set;} public string SampleConfig2 {get; set;}}
Next, we register this class through dependency injection.
IocManager.Register (); / / translator's note: a class is registered in IocManager, in other words, we can get an instance of this class MyModuleConfig through IocManager. As for the principle of IOC, I won't go into details here. In short, I can get an instance of a class.
Finally, we get a reference to the configuration by creating an extended method, IModuleConfigurations. The code is as follows:
Translator's note: the module configuration is a static class because we need to reuse it. The static method Mymodule returns a configuration interface with an argument to the ImoduleConfigurations interface.
Now, we can also configure our custom MyModule module in other modules.
Configuration.Modules.MyModule (). SampleConfig1 = false;Configuration.Modules.MyModule (). SampleConfig2 = "test"
In a sense, MyModule requires these configurations, and you can inject MyModuleConfig and use these values.
Public class MyService: ITransientDependency {private readonly MyModuleConfig _ configuration; public MyService (MyModuleConfig configuration) {_ configuration = configuration;} public void DoIt () {if (_ configuration.SampleConfig2 = = "test") {/ /...}
This means that all modules can be configured centrally in the system of the abp framework.
ABP dependency injection
What is dependency injection?
If you already know the concept of dependency injection, constructors, and attribute injection patterns, you can skip this section.
Wikipedia says: "dependency injection is one or more dependency injections (or services) of a software design pattern, or passed by reference, as part of the dependent object (or client) and client state. The behavior of establishing a customer dependency between patterns, which allows programming to be loosely coupled, relying on the principle of inversion and single responsibility. It is in direct contrast to the service locator model, which allows customers to understand the systems they are using to find dependencies. " .
Without dependency injection techniques, dependency management, modular development, and application modularization are difficult.
The problem of the traditional way
In an application, classes depend on each other. Suppose we have an application service that uses the repository class to insert entities into the database. In this case, the application service class depends on the repository class. Take a look at the example:
Public class PersonAppService {private IPersonRepository _ personRepository; public PersonAppService () {_ personRepository = new PersonRepository ();} public void CreatePerson (string name, int age) {var person = new Person {Name = name, Age = age}; _ personRepository.Insert (person);}}
PersonAppService uses PersonRepository to insert Person into the database. The problem with this code:
PersonAppService calls the CreatePerson method through IPersonRepository, so this method relies on IPersonRepository instead of the PersonRepository concrete class. But PersonAppService (the constructor of) still depends on PersonRepository. Components should rely on interfaces rather than implementations. This is the so-called principle of dependency inversion.
If PersonAppService creates PersonRepository itself, it becomes a concrete implementation that relies on the IPersonRepository interface and cannot use another implementation. Therefore, it makes no sense to separate the interface from the implementation in this way. Hard dependencies (hard-dependency) make code tightly coupled and less reusable.
We may need to change the way we create PersonRepository in the future. That is, we might want it to be created as a singleton (a single shared instance instead of creating an object for each usage). Or we might want to create multiple classes that implement IPersonRepository and create objects based on conditions. In this case, we need to modify all classes that depend on IPersonRepository.
With such dependencies, it is difficult (or impossible) to unit test PersonAppService.
To overcome these problems, you can use factory mode. Therefore, the repository class created is abstract. Look at the following code:
Public class PersonAppService {private IPersonRepository _ personRepository; public PersonAppService () {_ personRepository = PersonRepositoryFactory.Create ();} public void CreatePerson (string name, int age) {var person = new Person {Name = name, Age = age}; _ personRepository.Insert (person);}}
PersonRepositoryFactory is a static class that creates and returns an IPersonRepository. This is called the service locator mode. The above dependency problem is resolved because PersonAppService does not need to create an object that implements IPersonRepository, which depends on the Create method of PersonRepositoryFactory. However, there are still some problems:
At this point, PersonAppService depends on PersonRepositoryFactory. It is easier to accept, but there is still a hard dependency (hard-dependency).
Tediously write a factory class / method for each library or dependency.
Testability is still not good, because it is difficult to make PersonAppService use mock to implement IPersonRepository.
Solution:
There are some best practices (patterns) for class dependencies.
Constructor injection
Rewrite the above example as follows:
Public class PersonAppService {private IPersonRepository _ personRepository; public PersonAppService (IPersonRepository personRepository) {_ personRepository = personRepository;} public void CreatePerson (string name, int age) {var person = new Person {Name = name, Age = age}; _ personRepository.Insert (person);}}
This is called constructor injection. Right now, PersonAppService doesn't know which classes implement IPersonRepository and how to create it. Who needs to use PersonAppService, first create an IPersonRepository PersonAppService and pass it to the constructor, as follows:
Var repository = new PersonRepository (); var personService = new PersonAppService (repository); personService.CreatePerson ("Yunus Emre", 19)
Constructor injection is a perfect way to make a class create dependent objects independently. However, there are some problems with the above code:
It becomes difficult to create a PersonAppService. Imagine that if it had four dependencies, we would have to create those four dependent objects and pass them to the constructor PersonAppService.
Dependent classes may have other dependencies (in this case, PersonRepository may have dependencies). Therefore, we must create all dependencies for PersonAppService, dependencies for all dependencies, and so on. . In this way, dependencies make it too complicated for us to create an object.
Fortunately, the dependency injection framework manages dependencies automatically.
Attribute injection
The constructor injection pattern is a perfect way to provide class dependencies. In this way, you cannot create an instance of a class without providing dependencies. It is also a powerful way to explicitly declare what kind of requirements work correctly.
However, in some cases, this class depends on another class, but you can do without it. This usually applies to crosscutting concerns (such as logging). A class can not have a working log, but it can log if you provide a log object. In this case, you can define dependencies as public properties instead of having them placed in the constructor. Think about it, if we want to keep a journal on PersonAppService. We can rewrite the class as follows:
Public class PersonAppService {public ILogger Logger {get; set;} private IPersonRepository _ personRepository; public PersonAppService (IPersonRepository personRepository) {_ personRepository = personRepository; Logger = NullLogger.Instance;} public void CreatePerson (string name, int age) {Logger.Debug ("Inserting a new person to database with name =" + name); var person = new Person {Name = name, Age = age}; _ personRepository.Insert (person) Logger.Debug ("Successfully inserted!");}}
NullLogger.Instance is a singleton object that implements the ILogger interface, but actually does nothing (no logging). It implements the ILogger instance, and the method body is empty. Now, PersonAppService can log, if you set Logger for the PersonAppService instance, as follows:
Var personService = new PersonAppService (new PersonRepository ()); personService.Logger = new Log4NetLogger (); personService.CreatePerson ("Yunus Emre", 19)
Suppose Log4NetLogger implements an ILogger instance so that we can use the Log4Net library to write logs. Therefore, PersonAppService can write a journal. If we don't set up Logger,PersonAppService, we won't keep a log. Therefore, we can say that the PersonAppService ILogger instance is an optional dependency.
Almost all dependency injection frameworks support the attribute injection pattern
Dependency injection framework
There are many dependency injection frameworks that can automatically resolve dependencies. They can create all dependencies (recursive dependencies and dependencies). So you just need to write classes and class constructors & properties according to the injection pattern, and leave the rest to the DI framework! In good applications, classes are even independent of the DI framework. The entire application will have only a few lines of code or classes that appear to interact with the DI framework.
ABP's dependency injection is based on the Castle Windsor framework. One of the most mature DI frameworks of Castle Windsor. There are many such frameworks, such as Unity,Ninject,StructureMap,Autofac and so on.
When using a dependency injection framework, first register your interface / class with the dependency injection framework, and then you can resolve an object. In Castle Windsor, it goes like this:
Var container = new WindsorContainer (); container.Register (Component.For (). ImplementedBy (). LifestyleTransient (), Component.For (). ImplementedBy (). LifestyleTransient (); var personService = container.Resolve (); personService.CreatePerson ("Yunus Emre", 19)
We first created WindsorContainer. Then register PersonRepository and PersonAppService and their interfaces. Then we ask the container to create an instance of IPersonAppService. It creates the PersonAppService object and its dependencies and returns. In this simple example, using the DI framework may not be so straightforward, but imagine that you will have many classes and dependencies in a real enterprise application. Of course, registered dependencies are created only once somewhere the program starts.
Note that we are only talking about objects declared as temporary objects (transient). This means that every time we create an object of these types, a new instance is created. There are many different lifecycles (such as Singletion).
Infrastructure of ABP dependency injection
Following best practices and some conventions when writing applications, ABP almost makes the use of the dependency injection framework invisible.
Registration:
In ABP, there are many different ways to register your class with the dependency injection system. Most of the time, conventional methods are sufficient.
General registration:
By convention, ABP automatically registers all Repositories, Domain Services, Application Services, MVC and Web API controllers. For example, you might have an IPersonAppService interface and an implementation class PersonAppService:
Public interface IPersonAppService: IApplicationService {/ /...} public class PersonAppService: IPersonAppService {/ /...}
ABP automatically registers it because it implements the IApplicationService interface (it's just an empty interface). It will be registered as transient (an instance will be created for each use). When you inject (using constructor injection) the IPersonAppService interface into a class, the PersonAppService object is automatically created and passed to the constructor.
Naming conventions are very important here. For example, you can change the name PersonAppService to MyPersonAppService or another name that contains the suffix "PersonAppService", because IPersonAppService contains this suffix. But you can name your service class without following PeopleService. If you do this, it will not automatically register for IPersonAppService (it needs to be self-registration to the DI framework, not an interface), so you should register it manually if you want.
ABP registers the assembly by convention. Therefore, you should tell ABP to register your assembly as agreed. This is easy:
IocManager.RegisterAssemblyByConvention (Assembly.GetExecutingAssembly ())
Assembly.GetExecutingAssembly () gets a reference to the assembly that includes this code. You can register other assemblies through the RegisterAssemblyByConvention method. This is also done when your module is initialized (AbpModule.Initialize ()). Check out ABP's module system for more information.
You can implement the IConventionalRegisterer interface and call IocManager. The AddConventionalRegisterer method writes its own convention registration class. You should add it to the module's pre-initialize method.
Help interface
You can register for a specific class that does not follow the traditional convention rules. ABP provides shortcut methods for ITransientDependency and ISingletonDependency interfaces. For example:
Public interface IPersonManager {/ /...} public class MyPersonManager: IPersonManager, ISingletonDependency {/ /...}
In this way, you can easily register MyPersonManager as transient. MyPersonManager is used when IPersonManager needs to be injected. Note that the dependency is declared as a singleton. Therefore, the same object created MyPersonManager is passed to all required classes. If it is created only when it is used for the first time, then the entire life cycle of the application uses the same instance.
Custom / Direct Registration
If the methods described above are still not sufficient for your situation, you can use Castle Windsor to register classes and dependencies. Therefore, you will have all the capabilities of Castle Windsor registration.
You can implement the IWindsorInstaller interface to register. You can create a class in your application that implements the IWindsorInstaller interface:
Public class MyInstaller: IWindsorInstaller {public void Install (IWindsorContainer container, IConfigurationStore store) {container.Register (Classes.FromThisAssembly (). BasedOn (). LifestylePerThread (). WithServiceSelf ());}}
Abp automatically discovers and executes this class. Finally, you can get WindsorContainer by using the IIocManager.IocContainer attribute. For more information, read the documentation for Windsor.
Parsing (Resolving)
Register IOC (inversion of Control) containers about your classes, their dependencies, and their lifecycles. When your application needs to create objects using IOC containers, ASP.NET provides some ways to resolve dependencies.
Constructor & attribute injection
As a best practice, you can use constructors and property injection to obtain the dependencies of your class. Wherever possible, you should do this. Example:
Public class PersonAppService {public ILogger Logger {get; set;} private IPersonRepository _ personRepository; public PersonAppService (IPersonRepository personRepository) {_ personRepository = personRepository; Logger = NullLogger.Instance;} public void CreatePerson (string name, int age) {Logger.Debug ("Inserting a new person to database with name =" + name); var person = new Person {Name = name, Age = age}; _ personRepository.Insert (person) Logger.Debug ("Successfully inserted!");}}
IPersonRepository is injected from the constructor, and ILogger instances are injected from public properties. In this way, your code does not reflect the dependency injection system. This is the most appropriate way to use the DI system.
IIocResolver and IIocManager
Sometimes you may need to create your dependencies directly instead of constructors and property injections. This should be avoided as much as possible, but it may not be avoided. Abp provides services that make such an injection easy to implement. Example:
Public class MySampleClass: ITransientDependency {private readonly IIocResolver _ iocResolver; public MySampleClass (IIocResolver iocResolver) {_ iocResolver = iocResolver;} public void DoIt () {/ / Resolving, using and releasing manually var personService1 = _ iocResolver.Resolve (); personService1.CreatePerson (new CreatePersonInput {Name = "Yunus", Surname = "Emre"}); _ iocResolver.Release (personService1) / / Resolving and using in a safe way using (var personService2 = _ iocResolver.ResolveAsDisposable ()) {personService2.Object.CreatePerson (new CreatePersonInput {Name = "Yunus", Surname = "Emre"});}}
MySampleClass is a sample class for an application. IIcResolver injects through the constructor and then uses it to create and release objects. There are several workarounds for overloading that can be used as needed. The Release method is used to release the component (object). If you are creating an object manually, it is important to call the Release method to release the object. Otherwise, your application will have memory leaks. To ensure that the object is released, use ResolveAsDisposable whenever possible (as shown in the example above). It automatically calls the Release method when the using code block ends.
If you want to use the IOC container (Castle Windsor) directly to handle dependencies, you can inject IIocManager through the constructor and use its IIocManager.IocContainer property. If you are in a static context or cannot inject IIocManager, there is a last method, you can use the singleton object IocManager.Instance, you can get it anywhere, it is everywhere. However, in this case, your code will not be easy to test.
Append
IShouldInitialize interface:
Some classes need to be initialized before they are first used. IShouldInitialize has an Initialize () method. If you implement it, your Initialize () method is automatically called after the object is created (before using it). Of course, in order to use this feature, you should inject / create this object.
ASP.NET MVC & ASP.NET Web API integration:
Of course, we must invoke the dependency injection system to handle the root object of the dependency graph. In an ASP.NET MVC application, it is usually a controller class. We can use the constructor injection pattern to inject the controller. When a request comes to our application, the controller and all dependencies are created recursively by the IOC container. So, who did this? This is done automatically by the ASP.NET MVC default controller factory that Abp extends. ASP.NET Web API is similar. You don't have to care about the creation and release of objects.
Thank you for reading! This is the end of this article on "sample analysis of basic configuration and dependency injection in ABP framework". I hope the above content can be helpful to you, so that you can learn more knowledge. if you think the article is good, you can share it for more people to see!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.