如何在C#中合并/提取重复的代码结构

时间:2016-10-29 02:49:13

标签: c# .net c#-4.0

我的许多服务方法都遵循这种模式:

  public async Task<ApiResponseDto> DoSomething(string parameter1, string parameter2) // differing parameters
    {
        try // repeated
        {
           using (var db = new DbContext()) // repeated
           {
             // do stuff - this is where the unique stuff is
           }   
        }
        catch(Exception e){ // repeated
           HandleServiceLayerException();
        } 
     }

有什么方法可以把它提取到“足迹”中,所以我不必为每个服务层方法重复这些~10行吗?

3 个答案:

答案 0 :(得分:2)

您可以使用Sub Clear_PCOTCS() Dim myLastRow As Long Dim myRow As Long Application.ScreenUpdating = False myLastRow = Cells(Rows.Count, 14).End(xlUp).Row For myRow = myLastRow To 1 Step -1 If Cells(myRow, 14).Value = vbNullString Then Range(Cells(myRow, 14), Cells(myRow, 25)).Delete End If Next myRow Application.ScreenUpdating = True End Sub ,例如:

Func<DbContext, Task<ApiResponseDto>>

然后使用它,你可以像这样定义一个函数:

public async Task<ApiResponseDto> DBHelper(Func<DbContext,Task<ApiResponseDto>> apiRes) // differing parameters
{
    try // repeated
    {
        using (var db = new DbContext()) // repeated
        {
            // do stuff - this is where the unique stuff is
            var result = await apiRes(db);
            return result;
        }
    }
    catch (Exception e)
    { // repeated
        HandleServiceLayerException();
        return null;
    }
}

然后这样称呼它:

public async Task<ApiResponseDto> DoDBStuff(DbContext db)
{
    // Do specific stuff
}

答案 1 :(得分:1)

我想你可以轻松使用delegate参数来大大简化这些代码。

比如说,你真正需要的唯一参数是:

a。)两个字符串(parameter1parameter2)和

b。)DbContext

您可以创建以下委托:

public delegate void DoSomethingDelegate(string parameter1, string parameter2, DbContext db);

然后,您可以编写具有相同返回值和参数的函数 - 例如,

public void doSomethingSpecial(string parameter1, string parameter2, DbContext db)
{
   // do whatever you would do in the "special" part of your code.
}

然后,将其纳入您的方法:

public async Task<ApiResponseDto> DoSomething(string parameter1, string parameter2, DoSomethingDelegate doMethod) // differing parameters
{
    try // repeated
    {
       using (var db = new DbContext()) // repeated
       {
         doMethod(parameter1, parameter2, db);
       }   
    }
    catch(Exception e){ // repeated
       HandleServiceLayerException();
    } 
 }

然后,只需将方法名称传递给DoSomething的任何调用:

DoSomething(parameter1,parameter2, doSomethingSpecial);

答案 2 :(得分:1)

正如所承诺的那样 - 它基本上与Calmbit提出的想法相同,但允许您处理任何函数签名,因为您可以在函数对象的构造函数中传递参数。返回值类型在从抽象类继承时传递

using System;
using System.IO;
using System.Text;

namespace StackOverflowSnippets
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(DoSomething<Int32>(new CreateSumOf(30, 12)));
            Console.WriteLine(DoSomething<Int32>(new CreateDifferenceOf(30, 12)));
            Console.WriteLine(DoSomething<String>(new ConcatenateStrings("Function Objects ", "are cool")));
            Console.ReadLine();
        }

        // This part can be considered the Framework and only has to be created once
        public static T DoSomething<T>(Function<T> f)
        {
            try
            {
                using (Stream dbContext = new MemoryStream())
                {
                    return f.ServiceImpl(dbContext);
                }
            }
            catch (Exception)
            {
                // HandleServiceLayerException();
            }

            throw new InvalidOperationException();
        }
        public abstract class Function<T>
        {
            public abstract T ServiceImpl(Stream /* DbContext */ dbContext);
        }

        // Then create one class for every ServiceFunction
        public class CreateSumOf : Function<Int32>
        {
            private Int32 _a;
            private Int32 _b;

            public CreateSumOf(Int32 a, Int32 b)
            {
                _a = a;
                _b = b;
            }

            public override Int32 ServiceImpl(Stream /*DbContext*/ dbContext)
            {
                return (_a + _b);
            }
        }
        public class CreateDifferenceOf : Function<Int32>
        {
            private Int32 _a;
            private Int32 _b;

            public CreateDifferenceOf(Int32 a, Int32 b)
            {
                _a = a;
                _b = b;
            }

            public override Int32 ServiceImpl(Stream /*DbContext*/ dbContext)
            {
                return (_a - _b);
            }
        }
        public class ConcatenateStrings : Function<String>
        {
            private String _a;
            private String _b;

            public ConcatenateStrings(String a, String b)
            {
                _a = a;
                _b = b;
            }

            public override String ServiceImpl(Stream /*DbContext*/ dbContext)
            {
                StringBuilder b = new StringBuilder();

                b.Append(_a); 
                b.Append(_b);

                return b.ToString();
            }
        }
    }
}

神奇地给你

The answer