2010-10-05 5 views
1

J'essaye de remplir une vue d'arbre basée sur une liste de personnel de divers départements (lstStaff).Refactoriser ce code

public class Staff 
{ 
    public int StaffID { get; set; } 
    public string StaffName { get; set; } 
    public int DeptID { get; set; } 
    public string DepartmentName { get; set; } 
} 

Le résultat devrait ressembler à ceci:

Département A

  • John
  • Dave

Département B

  • Andy
  • Leon

J'ai écrit le code suivant. Cependant, je pense que le code devrait être refactorisé plus loin.

RadTreeNode deptNode; 
RadTreeNode staffNode; 
var departments = (from d in lstStaff 
        where !string.IsNullOrEmpty(d.DepartmentName) 
       select new { d.DeptId, d.DepartmentName }) 
       .Distinct(); 

foreach (var d in departments) 
{ 
    //add department node 
    deptNode = new RadTreeNode() 
    { 
     Value = d.DeptId, 
     Text = d.DepartmentName 
    }; 
    tvwDepartmentCases.Nodes.Add(deptNode); 

    //add staff nodes to department node 
    var staffs = lstStaff 
        .ToList() 
        .Where(x => x.DeptId == d.DeptId); 

    foreach (var s in staffs) 
    { 
     staffNode = new RadTreeNode() 
     { 
      Value = s.StaffID, 
      Text = s.StaffName 
     }; 
     deptNode.Nodes.Add(staffNode); 
    } 
} 

Tous les commentaires sont les bienvenus. Merci!

+1

Comment a-t-il été refait? À quelle fin? –

+0

Je pense juste que "Var départements" et la liaison au nœud de l'arbre peuvent être améliorés. – bla

+0

Je suppose que vous voulez dire le personnel de la classe publique. –

Répondre

2

Utilisez l'opérateur GroupBy, c'est facile et c'est tellement plus joli.

var departmentGroups = lstStaff.GroupBy(staff => 
    new { staff.DeptID, staff.DepartmentName }); 

foreach (var department in departmentGroups) 
{ 
    var deptNode = new RadTreeNode() 
    { 
     Value = department.Key.DeptID, 
     Text = department.Key.DepartmentName 
    }; 

    tvwDepartmentCases.Nodes.Add(deptNode); 

    foreach (var staffMember in department) 
    { 
     var staffNode = new RadTreeNode() 
     { 
      Value = staffMember.StaffID, 
      Text = staffMember.StaffName 
     }; 
     deptNode.Nodes.Add(staffNode); 
    } 
} 

Il est également plus faible complexité parce que vous n'êtes pas obligé de parcourir la collection de lstStaff pour chaque département.

+0

Votre code est court et gentil! Le problème est que certains membres du personnel ont "DepartmentName" vide, leur nom n'apparaîtra pas si vous regroupez par DeptID et DepartmentName. – bla

+0

Désolé, je viens de reproduire votre logique. Vous pouvez changer cela en 'lstStaff.GroupBy (staff => new {staff.DeptID}); ', ou même' lstStaff.GroupBy (staff => staff.DeptID); '. Que faites-vous si aucun membre du personnel d'un ministère ne possède un ministère? –

+1

Si vous supprimez 'DepartmentName' de la clé, vous pouvez le récupérer par' department.FirstOrDefault (staff =>! String.IsNullOrEmpty (staff.DepartmentName)). DepartmentName'. Ceci trouvera le premier nom de département non nul et non vide parmi le personnel de ce département. –

0

Je pense que ce que vous avez est assez simple et facile à lire. Il y a de la place pour l'amélioration des performances (probablement négligeable) mais vous sacrifieriez une certaine lisibilité. Cela dit, qu'est-ce que vous n'aimez pas dans votre solution actuelle que vous voudriez refactoring?

+0

L'utilisation de GroupBy augmenterait la lisibilité dans ce cas. –

0

Je dois courir pour travailler maintenant, mais je pense que vous avez fait trop d'interrogation dans la boucle. Vous devez utiliser .ToLookup pour créer une table de correspondance pour les groupes du personnel avant la boucle, et utiliser la table de recherche pour trouver les membres du personnel dans chaque département à la place.

1
var grping = from staff in lstStaff 
      where !String.IsNullOrEmpty(staff.StaffName) 
      group staff.StaffName by staff.DepartmentName; 

foreach (var deptGrp in grping) 
{ 
     //add a high level node using deptGrp.Key 
     foreach (var staffName in deptGrp) 
       //add a lower level node 
} 
0

Je voudrais écrire -

foreach(var member in lstStaff) 
var deptNode = FindDeptNode(member.DeptId, member.DeptName); 
deptNode.Add(member.StaffId, member.StaffName); 


.. // in FindDeptNode 

if(!departmentsTreeView.ContainssNode(deptId, deptName)) 
departmentsTreeView.Add(deptId, deptName); 

return departmentsTreeView[deptId, deptName]; 

vous pouvez convertir en forme compilable.

Cheers.

0

Je ferais un pas de plus et créerais les nœuds de personnel à partir de la requête. C'est plus clair pour moi car nous avons toutes les informations nécessaires pour créer le nœud à ce moment-là. Malheureusement, il n'est pas possible de créer le noeud de département dans la requête d'une manière propre et lisible.

var depts = from staff in lstStaff 
      where !string.IsNullOrEmpty(staff.DepartmentName) 
      group //staff nodes 
       new RadTreeNode //each item in the group is a node 
       { 
        Value = staff.StaffID, 
        Text = staff.StaffName, 
       } 
      by  //departments 
       new 
       { 
        staff.DeptID, 
        staff.DepartmentName, 
       }; 
foreach (var dept in depts) 
{ 
    var deptNode = new RadTreeNode 
    { 
     Value = dept.Key.DeptID, 
     Text = dept.Key.DepartmentName, 
    }; 
    deptNode.Nodes.AddRange(dept.ToArray()); 
    tvwDepartmentCases.Nodes.Add(deptNode); 
} 
Questions connexes