Preface: Busy eventful August with a little bit of weariness has come to an end, autumn September bearing the victory of the war 70 anniversary of the festive rushing. There is no preparation, nor does it seem to require any preparation, because life does not require much future time. Busy daily work, overtime, white overtime, forget to go to anger, forget to calculate the so-called value. Tianjin explosion accident time warns us of the impermanence of life, the deceased rest in peace, the living people have to continue to cherish life, away from harm. Wuhan, this hot city, although the value of the autumn, but still withstand the "Autumn Tiger" baking, the road transpiration of the hot air, the whole body pore open, sweat flow, in such a high temperature, it seems that sweat is squeezed dry, in fact, is squeezed dry more than sweat!!! urged urged urged What about the MEF? What about interface-oriented programming? Almost three people, but also learn young play moan, a bit of tender taste. No way, the idea of a runaway, a bit wild and difficult to tame the meaning. Okay, no, let's get to the point today.
The previous two chapters describe the simple usage of the lower MEF and the combination of MEF and warehousing, which is the end of the chapter. Grandpa Mao taught us to do things. In this article, bloggers intend to demonstrate the flexibility of using MEF by sharing an interface-oriented programming framework.
1, interface-oriented programming: have a certain programming experience Bo friends should be familiar with or understand this programming idea, layer and layer through the interface dependence, the lower level is not directly to provide services to the upper layer, but define a set of interfaces for the upper call. As for the specific business implementation, that is what needs to be done in the development, in the project architecture phase, only need to define the layer and layer of the interface between the dependencies, the framework, the compilation can be directly passed. Why should there be such a design? Since it is architecture design, it is of course to increase the flexibility of the architecture and reduce the dependency (coupling) between layers and layers. This is not a two-sentence clear, more detailed can be read: interface programming to explain (a)-the ideological foundation. This article I think the analysis is quite in place. Okay, don't talk nonsense, look at the code.
2, Bo in the spirit of "not to say clearly not to give up" principle, oneself from the beginning of a simple framework demo, of course, may not be much value for Daniel, but please do not joke Bo master constantly explore the courage. Let's take a look at the approximate structure of the frame.
The meaning of the following levels is first explained:
First, estm. Client
Estm. Client.Winform:Winform project, user UI presentation, this is nothing to say.
Estm. CLIENT.IBLL: The client IBLL interface layer that defines the client's business interface, remembering that this is simply providing interface functionality to the UI layer.
Estm. CLIENT.BLL: Client BLL implementation layer, for the implementation of the client IBLL interface layer, provides the UI layer is really business logic.
Second, Estm.common
ESTM.Common.Model: General Dtomodel layer, note that this is not the entity model of EF, but rather a model layer of data transformations defined by another.
Third, estm. Service
Estm. The Service.WCF:WCF host project, which provides the interface contract and implementation for WCF. The purpose of WCF here is to isolate the client and server code.
Estm. SERVICE.IBLL: The server-side IBLL interface layer, which defines the business interface for the WCF layer, is similar to the functionality of the ESTM.Client.IBLL layer.
Estm. SERVICE.BLL: The service end of the BLL implementation layer, the implementation of the service-side IBLL interface layer.
Estm. Service.dal: The server-side DAL data access layer, which uses EF to establish a database connection.
Then look at the call relationships between the levels:
Finally, the benefits of this design:
(1) The entire framework uses an interface-oriented programming model, each layer is not directly to its upper layer to provide services (that is, not directly instantiated in the upper layer), but by defining a set of interfaces, only to the upper layer exposes its interface function, the upper layer of the lower layer is only an interface dependency, and not rely on concrete implementation. It is said that the client IBLL interface layer only provides a set of interfaces for the UI layer to invoke, for the UI layer, it does not feel the presence of the client BLL implementation layer, at the extreme point, even if not write the BLL implementation layer, the project can be compiled through, because the function of the interface has been defined. As for the concrete realization, that is the business problem. When we need to change the business logic, we just need to change the code of the BLL implementation layer, for the IBLL interface layer and the upper UI do not have to make any changes, further, even the client BLL implementation layer is completely rewritten or replaced, the IBLL and UI layer can make no changes. This is also the biggest advantage of interface-oriented programming.
(2) The previous picture also mentions the Dtomodel layer, why should have dtomodel such an object, rather than directly to the EF's entity model to the front? Personal feel that there are two reasons: first, the security problem mentioned above, the client can always only operate Dtomodel, when the client submits data to the background, will always first convert the Dtomodel bit EF model, and then to operate the database, imagine, If the UI performance layer can directly manipulate the model of EF, whether it will cause the entry of the operation database is not the only problem; second, for example, the database has a and B two tables, we need to show the front-end A.1, A.2 Two field, also need to show B table B.3, B.4 field, when we use Dtomodel, only need to construct good one dto_model, there are 4 fields, the front end can be used directly, if not the DTO, or directly to the object, or a, b two tables of the model passed over the front-end construction, Either way it should not be easy to use a dto.
Of course these are bloggers own understanding, if Bo friends think there are problems can point out ~ ~
Well, having said so many frameworks, here's the point to get to today. See how MEF flies in the project ~ ~ First look at each layer of code:
(1) ESTM.Service.DAL a database connection via EF: The blogger dragged a user's table in order to test.
Base.cs inside the EF's context object via MEF:
public class Base { [Import] public DbContext entityframework {set; get;} Public Base () { ///Because there is an import here, you need to assemble MEF Regisgter (). Composeparts (this); } Public Compositioncontainer Regisgter () { var catalog = new Assemblycatalog (assembly.getexecutingassembly ( )); var container = new Compositioncontainer (catalog); return container; } }
Corresponds to the export in the MyModel.Context.cs under the edmx file
[Export (typeof (DbContext))] public partial class Entities:dbcontext {public entities () : Base ("Name=entities") { } protected override void Onmodelcreating (Dbmodelbuilder modelBuilder) { throw new Unintentionalcodefirstexception (); } Public dbset<tb_users> tb_users {get; set;} }
(2) ESTM.Service.IBLL service-side IBLL interface layer defines the server-side interface:
Public interface Iserviceuser { list<dto_users> getalluser (); void AddUser (Dto_users ouser); }
(3) ESTM.Service.BLL service end BLL Implementation Layer definition interface implementation:
[Export ("Users", typeof (Iserviceuser))] public class Serviceuser:iserviceuser {//Need attention: 1. Add Service reference in CLIENT.BLL Inside, so, the configuration of the WCF connection is copied to the WinForm project under App. Config inside the//2.dal inside the connection string is also copied into WCF, for the same reason as the public list<dto_users> getal Luser () {var lstres = new list<dto_users> (); var oservice = new DAL. Serviceuser (); var Lstefmodel = Oservice.getallusers (); Generally use AutoMapper to convert the model of EF into a DTO model.z here for testing, we'll switch manually. Use reflection to convert var Lstefmodelprop = typeof (Tb_users). GetProperties (); var lstdtomodelprop = typeof (Dto_users). GetProperties (); foreach (Var oefmodel in Lstefmodel) {var oresuser = new Dto_users (); foreach (Var oprop in Lstefmodelprop) {var odtomodelprop = Lstdtomodelprop.firstordefau LT (x = X.name = = oprop.name); if (Odtomodelprop = = null) {continue; } odtomodelprop.setvalue (Oresuser, Oprop.getvalue (Oefmodel)); } lstres.add (Oresuser); } return lstres; } public void AddUser (Dto_users ouser) {}
Note that there is a conversion between the model and the Dtomodel of EF in the BLL implementation layer, because the entity model of EF is taken in the Dal, and the Dtomodel model that needs to be uploaded to the front end is usually converted by third-party tools such as AutoMapper. I am here for the sake of simplicity myself by manually passing the reflection down.
(4) ESTM.Service.WCF service-side WCF host layer, defining the interface contract for WCF.
static void Main (string[] args) {var Struri = "Http://127.0.0.1:1234/MyWCF.Server"; Uri httpaddress = new Uri (Struri); using (ServiceHost host = new ServiceHost (typeof (Csoaservice)))//need to add System.systemmodel this dll .... Csoaservice This implementation class for the implementation of Icsoaservice, the WCF real implementation method again in this class {///////////////////////////////////////Add service section Point///////////////////////////////////////////////////Host. AddServiceEndpoint (typeof (Icsoaservice), New Wshttpbinding (), httpaddress),//icsoaservice This is an outward exposed interface if (hos t.description.behaviors.find<servicemetadatabehavior> () = = null) {Servicemetadata Behavior Behavior = new ServiceMetadataBehavior (); Behavior. Httpgetenabled = true; Behavior. Httpgeturl = httpaddress; Host. DESCRIPTION.BEHAVIORS.ADD (behavior); } host. Opened + = delegate { Console.foregroundcolor = Consolecolor.green; Console.WriteLine ("Mywcf.server service has started successfully. "+ Struri); }; Host. Open (); while (true) {console.readline (); } } }
[ServiceContract] Public interface Icsoaservice { [OperationContract] list<dto_users> GetAllUsers (); }
public class Csoaservice:icsoaservice { [Import ("Users")] public iserviceuser Service {set; get;} Public Csoaservice () { regisgterall (). Composeparts (this); } Public list<dto_users> GetAllUsers () { return service.getalluser (); } Public Compositioncontainer Regisgterall () { Aggregatecatalog aggregatecatalog = new Aggregatecatalog (); var thisassembly = new Directorycatalog (AppDomain.CurrentDomain.BaseDirectory, "*.dll"); AGGREGATECATALOG.CATALOGS.ADD (thisassembly); var _container = new Compositioncontainer (aggregatecatalog); return _container; } }
The code has no complicated logic, which is to register the MEF instantiation variable first and then take the value. [Import ("users")] here is the import, according to our first two articles, then there must be a [Export ("users") such export, so we can be based on the Iserviceuser interface to look down, Finally, you can find the following export in ESTM.Service.BLL:
[Export ("Users", typeof (Iserviceuser))] public class Serviceuser:iserviceuser { //... }
(5) ESTM.Client.IBLL Client IBLL interface layer
Public interface Imanageruser { list<dto_users> getalluser (); }
(6) ESTM.Client.BLL client BLL Implementation layer
[Export ("Users", typeof (Imanageruser))] public class Manageruser:imanageruser {public list<common.model.dto_users> getalluser () {
WCF service object var owcfservice = new Servicereference_mywcf.csoaserviceclient (); Return Owcfservice.getallusers (). ToList (); } }
In this layer, the data is called through the WCF service, so you need to add the WCF Service reference.
(7) ESTM.Client.Winform Client UI layer: Define a DataGridView presentation list:
public partial class Form1:form { [Import ("Users")] public imanageruser Manager {set; get;} Public Form1 () { InitializeComponent (); Regisgterall (). Composeparts (this); This.dataGridView1.DataSource = Manager.getalluser (); } Public Compositioncontainer Regisgterall () { Aggregatecatalog aggregatecatalog = new Aggregatecatalog (); var thisassembly = new Directorycatalog (AppDomain.CurrentDomain.BaseDirectory, "*.dll"); AGGREGATECATALOG.CATALOGS.ADD (thisassembly); var _container = new Compositioncontainer (aggregatecatalog); return _container; } }
Get results:
One of the advantages of using MEF in the first chapter of the preceding MEF is to reduce the coupling between layers and layers, and now we're going to combine the framework to say how it works. First, let's take a look at ESTM.Client.Winform's reference to this project:
It is not a reference to add the ESTM.Client.BLL layer, but we have the following code in Form1.cs:
public partial class Form1:form { [Import ("Users")] public imanageruser Manager {set; get;} Public Form1 () { InitializeComponent (); Regisgterall (). Composeparts (this); This.dataGridView1.DataSource = Manager.getalluser (); } Public Compositioncontainer Regisgterall () { Aggregatecatalog aggregatecatalog = new Aggregatecatalog (); var thisassembly = new Directorycatalog (AppDomain.CurrentDomain.BaseDirectory, "*.dll"); AGGREGATECATALOG.CATALOGS.ADD (thisassembly); var _container = new Compositioncontainer (aggregatecatalog); return _container; } }
The program runs, and after registering MEF you can see that the manager's variable value is the Manageruser object inside the ESTM.Client.BLL. This is the contribution of the MEF, and when called Regisgterall (), MEF automatically looks for matches based on the import and export, and automatically instantiates them. If there is no MEF, we have to add a ESTM.Client.BLL reference to the UI layer. Of Course there's a point to be aware of, Although the UI layer does not have to add a ESTM.Client.BLL reference, but because the Manageruser object is used in the UI, the UI layer Bin directory must have ESTM.Client.BLL.dll this file and the DLL required for the ESTM.Client.BLL project , you can manually copy these DLLs into the UI under the Bin directory. Even for the sake of simplicity, you can also add ESTM.Client.BLL this reference on the UI layer, but bloggers feel that this seems to violate the principle of interface-oriented programming, uncomfortable, but did not think of a better solution.
In the construction of this small framework process, bloggers encounter a few problems here and Bo friends to share:
1. Adding a service reference in CLIENT.BLL, because CLIENT.BLL is an internal repository, it eventually generates a DLL, so the configuration of the WCF connection is copied to the app. config under the WinForm project.
The connection string inside the 2.DAL is also copied to the WCF App. Config, for the same reason.
3. How to register MEF
Public Compositioncontainer Regisgterall () { Aggregatecatalog aggregatecatalog = new Aggregatecatalog (); var thisassembly = new Directorycatalog (AppDomain.CurrentDomain.BaseDirectory, "*.dll"); AGGREGATECATALOG.CATALOGS.ADD (thisassembly); var _container = new Compositioncontainer (aggregatecatalog); return _container; }
It can be drawn to a public place, not written in every place. Note that since the import and export of MEF involves multiple internal libraries, it is important to traverse all DLLs below the bin directory to find a match.
4.DAL layer can also do a package, Bo Master's project is to use the storage mode package EF, and then in the SERVICE.BLL call warehousing services to access the database.
Attach the source code, interested can study under!
Category: C
Interface-Oriented Programming