重构使用相同代码但内部使用不同方法的方法

时间:2015-12-30 11:01:58

标签: c# asp.net

我有一些方法是相同的,除了一行(我在对象客户端上调用不同的方法)。 我会有更多这样的方法。

除了使用Reflection之外,有没有解决方法?

 private void initClerks(Client client)
            {
                string[] pks = client.ClerksPKS.Trim(','). Split(',');

                foreach (string pk in pks)
                {
                    string data = JObject.Parse(DBUtils.GetData(Constants.DBProcedures.GetProcedures.GetWorkerDetailsByPkid, pk))[Constants.ResponseJson.Data].ToString();

                    client.addClerk(JsonConvert.DeserializeObject<Clerk[]>(data)[0]);

                }

            }


private void initManagers(Client client)
            {
                string[] pks = client.ManagerPK.Trim(',').Split(',');



                foreach (string pk in pks)
                {
                    string data = JObject.Parse(DBUtils.GetData(Constants.DBProcedures.GetProcedures.GetWorkerDetailsByPkid, pk))[Constants.ResponseJson.Data].ToString();
                    client.addManager(JsonConvert.DeserializeObject<Manager[]>(data)[0]);

                }

            }

4 个答案:

答案 0 :(得分:6)

您可以通过将操作传递给方法来完成此操作。像

这样的东西
private void actOnData(Client client, string[] pks, Action<Client, string> addThing)
{
    foreach (string pk in pks)
    {
        string data = JObject.Parse(DBUtils.GetData(Constants.DBProcedures.GetProcedures.GetWorkerDetailsByPkid, pk))[Constants.ResponseJson.Data].ToString();
        addThing(client, data);
    }
}

private void initClerks(Client client)
{
    string[] pks = client.ClerksPKS.Trim(',').Split(',');
    actOnData(client,pks,(c,d) => { c.addClerk(JsonConvert.DeserializeObject<Clerk[]>(d)[0]); });
}

private void initManagers(Client client)
{
    string[] pks = client.ManagerPK.Trim(',').Split(',');
    actOnData(client, pks, (c, d) => { c.addManager(JsonConvert.DeserializeObject<Manager[]>(d)[0]); });
}

答案 1 :(得分:4)

考虑到这不是外部遗留的lib我会建议重构Client类以简化它的API(我会改变更多,但让我们在某些时候停止)

伪代码:

// taking into account Client, manager all are workers
class Client
{
    // further whenever you need filter out managers use LINQ OfType<>
    List<Workers> workers;

    public void Add<T>(T worker) where T: Worker
    {
        workers.Add(client);
    }
}

请参阅Extract method方法,

private void Initialize<T>(Client client, string[] pks)
{
    foreach (string pk in pks)
    {
        string data = JObject.Parse(DBUtils.GetData(Constants.DBProcedures.GetProcedures.GetWorkerDetailsByPkid, pk))[Constants.ResponseJson.Data].ToString();
        client.Add(JsonConvert.DeserializeObject<T[]>(data)[0]);    
    }
}

private void initClerks(Client client)
{
    string[] pks = client.ClerksPKS.Trim(',').Split(',');
    Initialize<Clerk>(client, pks);
}

private void initManagers(Client client)
{
    string[] pks = client.ManagerPK.Trim(',').Split(',');
    Initialize<Manager>(client, pks);           
}

继续前进两个intiClerks / initmanagers看起来多余,只是对Initialize的内联调用(当然,如果整个代码库不比你在这里显示的更复杂)

答案 2 :(得分:2)

提取方法的典型路径是找到差异并声明相应的方法参数。我们采用您的initClerks方法,在里面找到Clerk这个词。其中有3个,其中一个是Type,因此我们将使用与T对应的泛型参数Clerk制作通用方法。映射将是这样的

(1)client.ClerksPKS映射到Func<Client, string>
(2)JsonConvert.DeserializeObject<Clerk[]>映射到JsonConvert.DeserializeObject<T[]>
(3)client.addClerk映射到Action<Client, T>

所以常用的方法就是

void Init<T>(Client client, Func<Client, string> getPKS, Action<Client, T> addItem)
{
    string[] pks = getPKS(client).Trim(','). Split(',');
    foreach (string pk in pks)
    {
        string data = JObject.Parse(DBUtils.GetData(Constants.DBProcedures.GetProcedures.GetWorkerDetailsByPkid, pk))[Constants.ResponseJson.Data].ToString();
        addItem(client, JsonConvert.DeserializeObject<T[]>(data)[0]);
    }
}

和用法

private void initClerks(Client client)
{
    Init<Clerk>(client, c => c.ClerksPKS, (c, x) => c.addClerk(x));
}

private void initManagers(Client client)
{
    Init<Manager>(client, c => c.ManagerPK, (c, x) => c.addManager(x));
}

答案 3 :(得分:0)

创建基类以在其基础Init方法中添加公共逻辑。 然后在实现BaseClientInitializer的类中重写Insert方法。这种设计模式称为模板方法。

public abstract class BaseClientInitializer
  {
    private string[] keys;
    public BaseClientInitializer(string[] keys)
    {
      this.keys = keys;
    }
public abstract void Insert(string data);

public void Init()
{
  foreach (string pk in keys)
  {
    var data = JObject.Parse(DBUtils.GetData(Constants.DBProcedures.GetProcedures.GetWorkerDetailsByPkid, pk))[
        Constants.ResponseJson.Data].ToString();
    this.Insert(data);
  }
}   


 }

public class Clerks : BaseClientInitializer
  {
    private Client client;
    public Clerks(Client client) : base(client.ClerksPKS.Trim(','). Split(','))
    {
      this.client = client;
    }

    public override void Insert(string data)
    {
      client.addClerk(JsonConvert.DeserializeObject<Clerk[]>(data)[0]);
    }
  }

private void initClerks(Client client)
{
     var clerksInitializer = new ClerksInitializer(client);
    clerksInitializer.Init();
}

对init管理员执行相同操作。 区别不仅在于插入方法,pks数组也不同:client.ClerksPKS.Trim(',')。拆分(',') - 用于职员和client.ManagerPK.Trim(',')。拆分(',')为经理。因此简单的提取方法将无法正常工作。