2015-12-30 57 views
4

我有一些除了一行(我称对象客户端上的不同方法)相同的方法。 我会有更多这样的方法。使用相同的代码,但内部不同的方法的重构方法

除了使用反射之外,是否有解决方案?

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]); 

       } 

      } 
+0

您解析JSON字符串,然后将其转换回字符串,然后将其反序列化... –

+2

“除了一行(我在对象客户机上调用不同的方法)相同” - 我计算了三个不同之处 - pks'被初始化,是的,'client'方法,也是'DeserializeObject'的类型参数。 –

+0

对我来说,这似乎更像是解决另一个问题的方法,这是存储主键(pks?)并获取数据的方式。你也许可以增强这些以更好地控制初始化过程。 –

回答

4

考虑到这是不是外在的传统的lib我建议重构客户端类以及简化其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);   
} 

中去˚F (或者说,如果整个代码库并不比你在这里显示的更复杂)

+1

他正在调用addClerk和addManager,所以不能只提取foreach。 –

+0

另外'DeserializeObject 'vs'DeserializeObject '。正如我在对这个问题的评论中所说的,我计算了三个差异而不是一个差异。 –

+1

哦,我错过了,我很抱歉。添加了泛型类型参数,并且addManager()调用会出现另一个问题将修复此问题 – sll

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

我喜欢你的解决方案,这正是我一直在寻找的。 –

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(',')。 Split(',') - 用于职员和客户。ManagerPK.Trim(',')。Split(',')为经理。所以简单的提取方法将无法正常工作。

+0

过度工程? :) – sll

+0

或者只是简单的面向对象的方式来提取共同的逻辑到可重用的小部件;) –

+0

@sll只要等到你看到'ClerksInitializerFactory'产生'ClerksInitializer's和'BaseInitializerFactory'它派生自! – bzlm

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)); 
} 
相关问题