StructureMap is also an excellent IoC framework. It has a long history and adopts the Apache protocol. Currently, it is still very active in development and the documents on the project homepage are also relatively complete.
Basic example
Download StructureMap. In the basic instance, you only need to reference the StructureMap. dll file and reference the namespace StructureMap.
The following is the sample code for using IoC. We want to create a ContactController and use IoC to provide IContactValidator and IContactRepository instance objects for the constructor of ContactController.
public class ContactEntity{ public string Name { get; set; } public DateTime Birthday { get; set; } public string IDCard { get; set; }}public interface IContactValidator{ bool Validate(ContactEntity contact);}public class ContactValidator : IContactValidator{ public bool Validate(ContactEntity contact) { Console.WriteLine(string.Format("Contact \"{0}\" has been validated.", contact.Name)); return true; }}public interface IContactRepository{ bool Save(ContactEntity contact);}public class ContactRepository : IContactRepository{ private string _connectionString; public ContactRepository(string connectionString) { this._connectionString = connectionString; } public bool Save(ContactEntity contact) { Console.WriteLine(string.Format("Contact \"{0}\" has been saved to:", contact.Name)); Console.WriteLine(this._connectionString); return true; }}public class ContactController{ private IContactValidator _validator; private IContactRepository _repository; public ContactController(IContactValidator validator, IContactRepository repository) { this._repository = repository; this._validator = validator; } public void Save(ContactEntity contact) { this._validator.Validate(contact); this._repository.Save(contact); }}
The following is the test code for StructureMap:
Static void Main (string [] args) {ObjectFactory. initialize (x => {x. for <IContactValidator> (). use <ContactValidator> (); x. for <IContactRepository> (). use <ContactRepository> (). ctor <ContactRepository> ("connectionString") // from app. the Connection-String in config reads the database Connection String // serves as the connectionString parameter value of the constructor. required toreceivetting ("Connection-String") ;}); ContactEntity contact = new ContactEntity () {Name = "Richie", Birthday = new DateTime (1970, 1, 1 ), IDCard = "490192197001016191"}; // different from Castle Windsor: ContactController does not need to be registered to StructureMap. // you can also use StructureMap to create instance objects, structureMap automatically processes ContactController = ObjectFactory Based on the constructor/dependency of the requested instance object and the component registered during initialization. getInstance <ContactController> (); controller. save (contact); Console. readKey ();}
The preceding StructureMap Registry DSL fluent interface registers dependent components (Castle Windsor also supports a similar method). These configurations can also use xml. In the following configuration, PlugginType and PluggedType are similar to the service and type configuration attributes in Windsor, that is, the service Interface and specific implementation class are formulated; the default implementation class of the interface specified by the DefaultInstance node is, similar to using the first configured node as the default implementation class in Windsor, StructureMap uses the DefaultInstance node. When multiple implementation classes are configured for an interface, Instance is used to configure nodes, the configuration node is identified by adding a key value. When you use ObjectFactory to obtain an instance object, you can specify this key value to obtain instance objects of different implementation classes. For detailed xml configuration instructions, refer to the official documentation of the project.
<configuration> <configSections> <section name="StructureMap" type="StructureMap.Configuration.StructureMapConfigurationSection,StructureMap"/> </configSections> <StructureMap MementoStyle="Attribute"> <DefaultInstance PluginType="StructureMap.Test.IContactValidator,StructureMap.Test" PluggedType="StructureMap.Test.ContactValidator,StructureMap.Test" Scope="Singleton" /> <DefaultInstance PluginType="StructureMap.Test.IContactRepository,StructureMap.Test" PluggedType="StructureMap.Test.ContactRepository,StructureMap.Test" Scope="Singleton" connectionString="server=localhost; User ID=root; Psw=dev; datasource=test;" /> </StructureMap></configuration>
You can change the initialization code to the following (specify to read the configuration from app. config, or use the default StructureMap. config file or custom config file ):
ObjectFactory.Initialize(x =>{ x.PullConfigurationFromAppConfig = true;});
The preceding example uses constructor injection. StructureMap also supports setter injection and other methods.
Other features
Automatic Scanning
StructureMap supports automatic scanning. The interface is like public void Scan (Action <IAssemblyScanner> action)
You can use the Action parameter of the scan method to specify the assembly to be scanned. By default, StructureMap scans the entire assembly type to find the types that use PluginFamily or Pluggable attribute, you can also specify some types of include and exclude in the action expression. The types that can be automatically scanned must have a public constructor, the constructor cannot have parameters of the basic type (there can be other types of parameters, StructureMap can automatically construct instance objects of these parameters, such as the default public constructor, or other types marked as accepted by StructureMap Container Management)
Lifecycle
StructureMap objects managed by the container. The Life Cycle supports the following (Scope configuration in xml, or related methods during initialization, such as CacheBy)
PerRequest: creates an instance object for each request.
Singleton: Singleton
ThreadLocal: Each thread corresponds to an instance.
HttpContext: Unique on an HttpContext
HttpSession: Unique on an HttpSession
Hybrid: Hybrid mode. If HttpContext exists, it is set to HttpContext; otherwise, it is set to the current thread.
In addition, StructureMap supports the use of custom lifecycles to implement the StructureMap. Pipeline. ILifecycle interface.
Interception Processing
The intercept processing of StructureMap is not to implement functions such as AOP, but to serve specific types of IoC.
For example, you can provide some method calls for a type and call these methods immediately after creating an instance object of this type. For example, sometimes, after creating an object instance, it may be similar to the Decorator mode, use another Decorator class to wrap the Instance Object and return it to the requester; or customize some interceptors so that StructureMap can create some objects and call these interceptors for processing, then return it to the requester.
AutoMock
One highlight of StructureMap is the support for Automatic Construction of Mock objects for testing. StructureMap supports RhinoMocks and Moq. A simple demonstration is as follows:
The preceding ContactController, ContactRepository, and ContactValidator classes are used for demonstration. The test code for creating an Auto Mock object is as follows (the namespace StructureMap. AutoMocking must be referenced ):
ObjectFactory.Initialize(x =>{ x.PullConfigurationFromAppConfig = true;});ContactEntity contact = new ContactEntity(){ Name = "Richie", Birthday = new DateTime(1970, 1, 1), IDCard = "490192197001016191"};var autoMock = new RhinoAutoMocker<ContactController>(MockMode.AAA);ContactController controller = autoMock.ClassUnderTest;controller.Save(contact);Console.ReadKey();
The process is as follows:
1. Search for the dependency between the ContactController constructor and find the IContactRepository and IContactValidator dependency objects.
2. Use the MockRepository. CreateMock <T> () method of RhinoMocks to create IContactRepository and IContactValidator instance objects.
3. Call the constructor of ContactController to create a ContactController object.
In the ContactController. Save method, we output the type information of IContactRepository and IContactValidator. The result is as follows: