如何通过实例方法使用反射

How to use Reflection with instance methods

如果我创建以下有关交易的方法:

public static int Insert(string processMethod, object[] processParameters, Type processType, object process, UserTransactionDTO transObj, string spPostConfirm, int toEmpNum,int confirmState)
        {
            int affectedRows = -7;
            using (IfxConnection conn = new IfxConnection(ConfigurationManager.ConnectionStrings["crms"].ToString() + " Enlist=true;"))
            {
                if (conn.State == ConnectionState.Closed)
                {
                    conn.Open();
                }
                using (IfxTransaction tran = conn.BeginTransaction())
                {

                    if (!string.IsNullOrEmpty(processMethod))//business Method
                    {
                        processParameters[1] = conn;
                        processParameters[2] = tran;
                        MethodInfo theMethod = processType.GetMethod(processMethod, new[] { processParameters.First().GetType(), typeof(IfxConnection), typeof(IfxTransaction) });
                        object res = theMethod.Invoke(process, processParameters);
                        transObj.ValuesKey = res.ToString();
                    }
                    if (!string.IsNullOrEmpty(transObj.ValuesKey))
                    {
                        affectedRows = RunPreConfirm(transObj.TaskCode, transObj.UserStateCode, transObj.ValuesKey, conn, tran, confirmState);//sp_confirm
                        if (affectedRows != 1)
                        {
                            tran.Rollback();
                            tran.Dispose();//Dispose
                            conn.Close();
                            conn.Dispose();
                            return -1;//Fail
                        }
                        affectedRows = InsertTrans(transObj, conn, tran);//MainTransaction --->df2usertrans

                        if (affectedRows == 1)//Success
                        {

                            if (!string.IsNullOrEmpty(spPostConfirm))
                            {
                                affectedRows = RunPostConfirm(spPostConfirm, transObj.ValuesKey, conn, tran);//sp_post_confirm
                                if (affectedRows != 0)
                                {
                                    tran.Rollback();
                                    tran.Dispose();//Dispose
                                    conn.Close();
                                    conn.Dispose();
                                    return -2;//Fail 
                                }

                            }

                            affectedRows = RunAfterTrans(transObj.TaskCode, transObj.OldStatusCode, transObj, toEmpNum, conn, tran);//sp_after_trans
                            if (affectedRows != 1)
                            {
                                tran.Rollback();
                                tran.Dispose();//Dispose
                                conn.Close();
                                conn.Dispose();
                                return -3;//Fail
                            }

                            tran.Commit();
                            tran.Dispose();
                            conn.Close();
                            conn.Dispose();
                            return 1;

                        }
                        else
                        {
                            tran.Rollback();
                            tran.Dispose();//Dispose
                            conn.Close();
                            conn.Dispose();
                            return -1;//Fail 
                        }
                    }
                    else
                    {
                        tran.Rollback();
                        tran.Dispose();//Dispose
                        conn.Close();
                        conn.Dispose();
                        return -1;//Fail 
                    }
                }
            }
            return affectedRows;
        }

我想请教三个问题:

1-如果我的内部方法之一未能在 } 之前插入,连接和事务是否自动处理和关闭?我的意思是我应该调用以下代码块:

tran.Dispose();
conn.Close();
conn.Dispose();

2-我可以调用实例方法及其属性,而不是填充对象并将其再次作为参数传递吗?

 object res = theMethod.Invoke(process, processParameters);

我的意思是: 我想使用它(及其对象状态),因为它是实例方法:

 public string InsertRequest(IfxConnection conn,IfxTransaction trans)

而不是当前的方法:

 public string InsertRequest(EnhancementRequest obj, IfxConnection conn,IfxTransaction trans)

3-下面的代码写得好吗?我的意思是,没有多余的步骤,也没有逻辑错误。?

代码有一些冗余和一些可能的问题。

首先,如果您使用 using 语句缩小连接和事务对象的范围,则不需要对这些对象中的任何一个调用 Dispose,因为 using 会为您处理。

如果调用存储过程的函数不处理数据库异常,您应该添加 try .. except aroung 您的事务范围:

   using (IfxTransaction tran = conn.BeginTransaction())
   {
      try
      {
         // All db operations here
         tran.Commit();
      }
      catch(Exception e)
      {
         tran.Rollback();
         throw; // Or return error code
      }
   }

如此有效,如果某些非异常验证条件失败,您只需要调用 trans.Rollback() 和 return 您的错误代码。

关于你的问题 2,我建议添加泛型调用作为你的函数参数:

public static int Insert(Func<IfxConnection, IfxTransaction, object> callback)
{
   // ...
   object res = callback(conn, tran);
   // ...
}

在上面的代码中我使用了泛型委托 Func,你可以这样调用你的插入函数:

Insert((conn, tran) =>
{
    // do something here with conn and tran and return object
});

或者,您可以声明自己的委托签名,如果您打算在将来更改它,这会很有帮助:

public delegate object MyDelegateType(IfxConnection conn, IfxTransaction tran);

然后在调用 insert 时将您选择的对象和方法作为参数传递:

public class SomeClass
{
    public static object ProcessOnInsert(IfxConnection conn, IfxTransaction tran)
    {
        // do something here with conn and tran
    }

    public static int Insert(MyDelegateType callback)
// or
//    public static int Insert(Func<IfxConnection,IfxTransaction,object> callback)
    {
        // ...
        callback(conn, tran);
        // ...
    }

    public static void RunInsert()
    {
        Insert(ProcessOnInsert);
    }
}

修改后的方法:

public static int Insert(Func<IfxConnection, IfxTransaction, object> processMethod, UserTransactionDTO transObj, string spPostConfirm, int toEmpNum, int confirmState)
{
    int affectedRows = -7;
    using (IfxConnection conn = new IfxConnection(ConfigurationManager.ConnectionStrings["crms"].ToString() + " Enlist=true;"))
    {
        if (conn.State == ConnectionState.Closed)
        {
            conn.Open();
        }
        using (IfxTransaction tran = conn.BeginTransaction())
        {
            try
            {
                if (processMethod != null)//business Method
                {
                    object res = processMethod(conn, tran);
                    transObj.ValuesKey = res.ToString();
                }
                if (string.IsNullOrEmpty(transObj.ValuesKey)) //Fail
                {
                    tran.Rollback();
                    return -1;//Fail 
                }

                affectedRows = RunPreConfirm(transObj.TaskCode, transObj.UserStateCode, transObj.ValuesKey, conn, tran, confirmState);//sp_confirm
                if (affectedRows != 1)
                {
                    tran.Rollback();
                    return -1;//Fail
                }

                affectedRows = InsertTrans(transObj, conn, tran);//MainTransaction --->df2usertrans
                if (affectedRows != 1)//Fail
                {
                    tran.Rollback();
                    return -1;//Fail 
                }

                if (!string.IsNullOrEmpty(spPostConfirm))
                {
                    affectedRows = RunPostConfirm(spPostConfirm, transObj.ValuesKey, conn, tran);//sp_post_confirm
                    if (affectedRows != 0)
                    {
                        tran.Rollback();
                        return -2;//Fail 
                    }
                }

                affectedRows = RunAfterTrans(transObj.TaskCode, transObj.OldStatusCode, transObj, toEmpNum, conn, tran);//sp_after_trans
                if (affectedRows != 1)
                {
                    tran.Rollback();
                    return -3;//Fail
                }

                tran.Commit();
                return 1;
            }
            catch
            {
                trans.Rollback();
                throw;
            }
        }
    }
    return affectedRows;
}

调用此函数时,只需传递任何具有匹配签名的实例方法作为 processMethod。

另一个建议是更改所有函数以使用类似的回调语法,而不是传递字符串和对象参数,而是直接调用方法,因为强类型在这种情况下提供了更多的可读性。

关于交易中一系列操作 运行 的可读性,如果任何一个失败,整个交易都需要失败,最好减少嵌套条件并首先检查失败(见上文)。