Use system.reflection.emit to generate call storage procedures

xiaoxiao2021-03-06  70

/ ************************************************** **************** * * Use system.reflection.emit to generate the realization of call storage procedures! * * By http://lostinet.com * * Copyrights: not-reverse * / ****************************************** ******************************* /

// Use example namespace lostinet.sample {using system; using system.data; using system.data.sqlclient; use system.windows.form;

/ / Define an interface to define the stored procedure

Interface inorthWindStoredProcedProcedures {// Define the method of the stored procedure

DataSet CustOrd (String Customerid);

// If the stored procedure name and method name are different, you should use SQLAccessAttribute to explain [SQLACCESS ("Employee Sales By Country)] DataTable EmployeesaSbyCountry (DateTime Beginning_date, DateTime Ending_date);

// ... more ...

// more ideas ..

/ / Direct SQL statement directly? //[Sqlaccess (sqlaccesstype.sqlQuery, "select * from employees where urgeyeeid = @ Empid ")] // DataTable selectemPloyee (int EmpID);}

class ConsoleApplication {[STAThread] static void Main (string [] args) {using (SqlConnection conn = new SqlConnection ( "server = (local); trusted_connection = true; database = northwind")) {// implementation creates sentence put ! // Need to be like SqlConnection and SqlTransaction // SqlTransaction can be null

// This is nice, can be obtained as long as SqlConnection / SqlTransaction able to use this method, so compatible Lostinet.Data.SqlScope INorthwindStoredProcedures nsp = (INorthwindStoredProcedures) StoredProcedure.CreateStoredProcedureInterface (typeof (INorthwindStoredProcedures), conn, null);

// Call the storage process and display

Showdata ("CustOrhist Alfki", Nsp.CustOrhist ("Alfki")); showdata ("Employee Sales By Country, Nsp.employeesaSbyCountry (New DateTime (1998, 1, 1), New DateTime (1999, 1, 1))) );

}

Static void showdata (string title, object data) {form f = new form (); f.Width = 600; f.height = 480; f.Text = title;

DataGrid Grid = New DataGrid (); Grid.dock = DockStyle.Fill; Grid.DataSource = DATA;

F.Controls.Add (grid); f.Showdialog ();

}

#REGON / / Implementation method (incomplete) Namespace Lostinet.sample {using system; using system.collections; useing system.reflection; using system.data; using system.data.sqlclient;

// This class is the base class for implementation, // is the purpose of providing some methods of saving SQLConnection / SqlTransAction and public use must be public, otherwise the developer does not explicitly access this class public Class SpinterfaceBase : Idisposable {public spinterfacebase () {}

Public void dispose () {}

// CreateStoredProcedureInterface will save the associated value SQLCONNECTION / SQLTRRANSACTION here public SqlConnection Connection; Public SqlTransaction Transaction;

// Create a SqlCommand public SqlCommand CreateCommand (string spname) {SqlCommand cmd = new SqlCommand (spname, connection, transaction); cmd.CommandType = CommandType.StoredProcedure; // TODO: //cmd.Parameters.Add("@ReturnValue " , ... Return CMD;

// Established SqldbType by Type, unfinished SQLDBTYPE GETSQLDBTYPE (Type Type) {///todo:switch (Type )..Return Sqldbtype.nvarchar;}

// define parameters public void DefineParameter (SqlCommand cmd, string name, Type type, ParameterDirection direction) {SqlParameter param = new SqlParameter ( "@" name, GetSqlDbType (type)); param.Direction = direction; cmd.Parameters.Add (Param);

// Set the parameter value PUBLIC VOID SetParameter (sqlcommand cmd, string name, object value) {cmd.parameters ["@" name] .value = (value == null);} // After the SQLCommand is executed, the parameter value public object getParameter (SQLCOMMAND CMD, String Name) {return cmd.parameters [@ " name] .value;}

/ / Perform different operations according to different return values

public SqlDataReader ExecuteDataReader (SqlCommand cmd) {return cmd.ExecuteReader ();} public object ExecuteScalar (SqlCommand cmd) {return cmd.ExecuteScalar ();} public void ExecuteNonQuery (SqlCommand cmd) {cmd.ExecuteNonQuery ();} public DataSet ExecuteDataSet (SqlCommand cmd) {DataSet ds = new DataSet (); using (SqlDataAdapter sda = new SqlDataAdapter (cmd)) {sda.Fill (ds);} return ds;} public DataTable ExecuteDataTable (SqlCommand cmd) {DataTable table = new DataTable (); Using (SqlDataAdapter SDA = New SqldataAdapter (CMD)) {sda.fill (Table);} Return Table; DataRow ExecuteTarow (SQLCOMMAND CMD) {DataTable Table = ExecuteTedATABLE (CMD); if (Table.Rows.count == 0) Return Null; Return Table.Rows [0];}}

public class StoredProcedure {static public object CreateStoredProcedureInterface (Type interfaceType, SqlConnection connection, SqlTransaction transaction) {// check parameters if (interfaceType == null) throw (new ArgumentNullException ( "interfaceType")); (! interfaceType.IsInterface) if throw ( new ArgumentException ( "argument is not interface", "interfaceType")); if (connection == null) throw (new ArgumentNullException ( "connection"));!! if (transaction = null) {if (transaction.Connection = connection "New ArgumentException (" Transaction.Connection! = Connection "," Transaction "));} // Create StoredProcedure

STOREDPROCEDURE SPEMIT = New StoredProcedure (); SPEMIT.ITERFACITYPE = InterfaceType; SPEMIT.CONNECTION = Connection; SPEMIT.TRANSACTION = Transaction;

// Create Return SPEMIT.CREATEINSTANCE ();

// Used to store the created type Static HashTable EmittedTypes = new hashtable (); type interface; sqlConnection connection; sqltransaction

Private storedprocedure () {}

Object createInstance () {lock (interface (interface (interface (interface "{// If there is no specific implementation, create it

IF (EmittedType == Null) {EmittedType = (Type) EmittedTypes [InterfacePe];

IF (EmitType == NULL) {createType (); // Store created type EmittedTypes [interfaceType] = EmittedType;}}}

// Create a specific instance spinterfacebase spi = (spinterfacebase) activator.createinstance (EmittedType);

// Set sqlconnection / sqltransaction spi.connection = connection; spi.transaction = transaction;

Return SPI;

TYPE EmittedType;

Typebuilder Typebuilder;

// Create the type of void CreateType () {// create Assembly //AssemblyBuilderAccess.Run- indicates that only used to run, not on the disk to save AssemblyName an = new AssemblyName (); an.Name = "Assembly." InterfaceType.FullName " . IMPLEMENTATION "; askMBLYBUILDER Asmbuilder = Appdomain.currentDomain.defineDynamicassembly (an, assemblybuilderccess.run);

// Create Modui ModuleBuilder MDLBuilder = asmbuilder.defineDynamicModule ("Module." InterfacePe.FullName ". Implementation");

// Create Type, inherits spinterfacebase type typebuilder = mdlbuilder.definetype (InterfaType.FullName ". Implementation", typettributes.class, typeof (spinterfacebase);

// Implement all interface methods EMITINTERFACE (InterfaType);

// If InterfaType is based on other interfaces (Type Subinterface ") {// idisposable does not need to be implemented, the spinterfacebase implements if (Subinterface == TypeOf (iDisposable)) Continue;

EmitInterface;} EmittedType = Typebuilder.createType ();

Void EmitInterface (Type Type) {// Implement the interface typebuilder.addinterfaceImplement (Type);

// List the member of the interface for Foreach (MemberInflags.instance | BindingFlags.Public)) {// Convention - Members must be a method, no properties, IFs such as events (Member.Membertype! = MEMBERTYPES.METHOD) THROW (New Exception MEMBER.MEMBERTYPE "Automatically!");

// Get the method defined in the interface MethodInfo Method = (MethodInfo) MEMBER;

// Calculate new methods properties, properties that are replicated in the method over and not Public / Abstract, plus Private MethodAttributes methodattrs = method.Attributes; methodattrs & = ~ (MethodAttributes.Public | MethodAttributes.Abstract); methodattrs | = MethodAttributes .PriVate;

Parameterinfo [] paraminfos = method.getParameters (); int paramlength = paraminfos.length;

// Number of types of parameters Type [] paramtypes = new type [paramth]; for (int i = 0; i

// Establish a new method on TypeBuilder, the parameter type and the return type are consistent with the method of the interface Methodbuilder Mthbuilder = typebuilder.defineMethod (Method.Name, Methodattrs, method.callingconvention, method.Returntype, paramtypes);

/ / Copy the name and attribute for the parameters on the new method for (int i = 0; i

/ / Define a field on the type, this field is used to store the SQLCommand FieldBuilder Field_cmd = typebuild.definefield ("_ cmd _" method.name, typeof (sqlcommand), Fieldattributes.private;

// ilgenerator is an object ILGENERATOR ILG = mthbuilder.getilGenerator () for generating an object that implements code.

// Define a temporary variable localbuilder local_res = ilg.declareLocal (TypeOf (Object));

/ / Define a label label label_cmd_ready = ilg.defineLabel () for jump.

//this._cmd_methodname ilg.emit (opcodes.ldarg_0); // this ilg.emit (opcodes.ldfld, field_cmd); //._ cmd_methodname

//if (THIS._CMD_METHODNAME !=NULL) jumps to label_cmd_ready ilg.emit (opcodes.brtrue, label_cmd_ready);

// If this._cmd_methodname is NULL, run the following code to create SQLCommand

//this._cmd_methodname=this.createCommand ("methodname "); Ilg.emit (opcodes.ldarg_0);

//this.createCommand Ilg.emit (opcodes.ldarg_0); // Parameter 0 ILG.Emit (opcodes.ldstr, sqlaccessattribute.getspname (Method)); // Parameter 1 // Call ilg.emit (Opcodes.callvirt, Typeof (Spinterfacebase) .getMethod ("CreateCommand", BindingFlags.instance | BindingFlags.public);

ilg.Emit (OpCodes.Stfld, field_cmd); // ._cmd_MethodName = // this.DefineParameter (...) if (! paramlength = 0) {// obtain DefineParameter REFERENCE MethodInfo method_DefineParameter = typeof (SPInterfaceBase) .GetMethod ( "DefineParameter", bindingflags.instance | bindingflags.public); for (int i = 0; i

//this.defineParameter(th._cmd_methodname, "parameeeeeeee "", ParameterDirection.xxx);

// Parameter 0 - this ilg.emit (opcodes.ldarg_0);

// Parameter 1 - this._cmd_methodname ilg.emit (opcodes.ldarg_0); Ilg.emit (Opcodes.ldfld, Field_CMD);

// Parameter 2 - "ParameterName" ilg.emit (opcodes.ldstr, pi.name);

// Parameter 3 - TypeOf (ParameterType) ilg.emit (opcodes.ldtoken, pi.parameterType);

// Parameter 4 - ParameterDirection.xxx if (pi.ParameterType.isByref) {ilg.emit (Opcodes.ldc_i4, (int) parameterdirection.inputoutput);} else if (pi.isout) {ipg.emit (opcodes.ldc_i4, (int) parameterdirection.output;} else {ilg.emit (opcodes.ldc_i4, (int) parameterDirection.input);} // call defineParameter ilg.emit (opcodes.callvirt, method_defineparameter);}} // Cmd_commandname has OK.

// Set label_cmd_ready refers to ilg.marklabel (label_cmd_ready); // cmd! = Null now.

IF (paramlength! = 0) {// Now set the value of the parameters of the method to SQLParameter

MethodInfo method_SetParameter = typeof (SPInterfaceBase) .GetMethod ( "SetParameter", BindingFlags.Instance | BindingFlags.Public); for (int i = 0; i

// If the parameter is OUT, you do not need to set if (! Pi.parametertype.isbyref && pi.isout) Continue;

//this.SetParameter (THIS._CMD_METHODNAME, "Parametername ";ilg.emit (opcodes.ldarg_0); ilg.emit (opcodes.ldarg_0); Ilg.emit (Opcodes.ldfld, Field_CMD);

Ilg.emit (opcodes.ldstr, pi.name);

// Get the parameter value, if the parameter is ValueType, then Box to Object Ilg.emit (OpCodes.ldarg, i 1); if (Pi.ParameterType.isValueType) ilg.emit (opcodes.box, pi.parametertype);

Ilg.emit (opcodes.callvirt, method_setparameter);}}

/ / Now to perform a storage process (executive sqlcommand)

// This here, based on the return value type, how to perform SQLCommand

TYPE RTURNTYPE = Method.Returntype;

// If it is void, you do not need to return a value Bool Nores = RetURNTYPE == TypeOf (Void);

MethodInfo method_execute = NULL;

if (nores) {// no return value method_Execute = typeof (SPInterfaceBase) .GetMethod ( "ExecuteNonQuery", BindingFlags.Instance | BindingFlags.Public);} else if (returnType == typeof (object)) {// return object method_Execute = typeof (SPInterfaceBase) .GetMethod ( "ExecuteScalar", BindingFlags.Instance | BindingFlags.Public);} else if (returnType == typeof (DataSet)) {// return DataSet method_Execute = typeof (SPInterfaceBase) .GetMethod ( "ExecuteDataSet ", Bindingflags.instance | bindingflags.public);} else if (returnty == typeof (data)) {// Return DataTable method_execute = typeof (Spin terfaceBase) .GetMethod ( "ExecuteDataTable", BindingFlags.Instance | BindingFlags.Public);} else if (returnType == typeof (DataRow)) {// return DataRow method_Execute = typeof (SPInterfaceBase) .GetMethod ( "ExecuteDataRow", BindingFlags. Instance | bindingflags.public);

} Else {// return other types foreach (Type retInterface in returnType.GetInterfaces ()) {// if it is returned IDataReader if (retInterface == typeof (IDataReader)) {// only supports SqlDataReader if (! ReturnType.IsAssignableFrom (typeof (SqlDataReader))) throw (new Exception ( "SqlDataReader could not convert to" returnType.FullName)); method_Execute = typeof (SPInterfaceBase) .GetMethod ( "ExecuteDataReader", BindingFlags.Instance | BindingFlags.Public); break;}} }

/ / If the appropriate policy is not found, if (Method_execute == Null) {// Todo: Of course, there should be returning Int32, string, ..., but too lazy to write.

// Throw an exception, the prompt does not support the return type, the author is changed :) throw ("Notsupport ReturntYpe:" Returntype.Fullname);}

//this.ExecuteXXX(this._cmd_MethodName) ilg.Emit (OpCodes.Ldarg_0); ilg.Emit (OpCodes.Ldarg_0); ilg.Emit (OpCodes.Ldfld, field_cmd); ilg.Emit (OpCodes.Callvirt, method_Execute);

// If there is a return value, it is //local_res=this.executexxxx(this_cmd_methodname) ife (! Nores) {if (returntype.isvalueType) ilg.emit (opcodes.box, returnty); Ilg.emit (opcodes .Stloc, local_res);!} if (paramlength = 0) {// here treated ref / out parameters MethodInfo method_GetParameter = typeof (SPInterfaceBase) .GetMethod ( "GetParameter", BindingFlags.Instance | BindingFlags.Public); for (int I = 0; i

// If it is not REF / OUT, skip the IF (! Pi.parametertype.isbyref &&! Pi.isout) Continue;

//Parametername =tHis.getParameter (this._cmd_methodname ") ilg.emit (opcodes.ldarg_0); ilg.emit (opcodes.ldarg_0); ilg.emit (opcodes.ldfld, field_cmd);

Ilg.emit (opcodes.ldstr, pi.name);

Ilg.emit (opcodes.callvirt, method_getparameter);

// If the type is the value type, you need UNBOX if (Pi.ParameterType.isValueType) ilg.emit (opcodes.unbox, pi.parametertype);

Ilg.emit (Opcodes.Starg, i 1);}}

// If it is void, then directly return; // is return local_res, if the return value type is ValueType, you need UNBOX if (! NORES) {ilg.emit (opcodes.ldloc, local_res); if (Returntype.IsValueType ) ilg.Emit (OpCodes.Unbox, returnType);} ilg.Emit (OpCodes.Ret); // // throw (new NotImplementedException ()); // ilg.Emit (OpCodes.Newobj, typeof (NotImplementedException) .GetConstructor (New Type [0]))); // ilg.emit (opcodes.throw);

}}}

Public Enum SQLACCESSTYPE {StoredProcedure // Todo: //, SQLQuery}

[AttributeUSAGE (AttributeTargets.method)] public class sqlaccessattribute: attribute {string _sp;

Public SQLACCESSATTRIBUTE (STRING SPNAME) {_SP = SPNAME;

Public string storeprocedure {get {return _sp;}}

Static Public String GetSpname (Method Info Method) {if (Method == Null) Throw ("Method");

Object [] attrs = method.getcustomattributes (TypeOf (SqlaccessAttribute), false; if (attrs == null || attrs.length == 0) Return Method.Name;

Return (SQLACCESSATTRIBUTE) Attrs [0]). storeprocedure;}

// Todo: // public sqlaccessattribute (SQLACCESSTYPE TYPE, STRING TEXT) / / {////}}} #ENDREGON

转载请注明原文地址:https://www.9cbs.com/read-88169.html

New Post(0)