如何避免代码重复

时间:2010-07-08 12:20:11

标签: c#

我有以下代码,我想以一种最少的代码行编写它,并且工作方式相同。我怎样才能做到这一点?

List<Category> categoryList = new List<Category>();
categoryList = Category.LoadForProject(project.ID).ToList();
List<string> categories = new List<string>(Categories);
IList<Category> currentCategories = Category.LoadForProject(project.ID).ToList();
if (currentCategories != null)
{
    foreach (var existingCategories in currentCategories)
    {
        if (categories.Contains(existingCategories.Name))
           categories.Remove(existingCategories.Name);
        else
            existingCategories.Delete(Services.UserServices.User);
    }
    foreach (string item in categories)
    {
        Category category = new Category(project, item.ToString());
        category.Project = project;
        category.Save();
   }
}

List<string> priorities = new List<string>(Priorities);
IList<Priority> currentPriorities = Priority.LoadForProject(project.ID).ToList();
if (currentPriorities != null)
{
   foreach (var existingPriorities in currentPriorities)
   {
       if (priorities.Contains(existingPriorities.Name))
           priorities.Remove(existingPriorities.Name);
       else
           existingPriorities.Delete(Services.UserServices.User);
   }
   foreach (string item in priorities)
   {
       Priority priority = new Priority(project, item.ToString());
       priority.Project = project;
       priority.Save();
   }
}

6 个答案:

答案 0 :(得分:9)

这样的事情应该这样做:

public IList<T> DoYourThing<T>(IList<T> items, IList<T> currentItems, Project project) where T : CommonBaseType
{
  if (currentItems != null)
  {
    foreach (var existingItem in currentItems)
    {
      if (items.Contains(existingItem.Name))
        items.Remove(existingItem.Name);
      else
        existingItems.Delete(Services.UserServices.User);
    }
    foreach (string item in items)
    {
      T newItem = Activator.CreateInstance(typeof(T), new object[] {project, item.ToString()}) as T;
      newItem.Project = project;
      newItem.Save();
    }
  }

  return currentItems;
}

然后你可以这样称呼它:

var currentCategories = DoYourThing(Categories.ToList(), Category.LoadForProject(project.ID).ToList());
var currentProjects = DoYourThing(Priorities.ToList(), Priority.LoadForProject(project.ID).ToList());

最后,你应该特别注意两件事: 首先,函数where T : CommonBaseType有一个通用条件。我假设Category和Project有一个包含Name的公共基类型或接口。如果没有,你应该摆脱这种情况,并使用动态获取名称。

其次,我正在使用Activator.Create为您创建类。如果你不知道那个技巧那么这很难弄清楚

祝你好运!

答案 1 :(得分:7)

使优先级和类别实现相同的接口,或者从具有公共属性的类派生(即.Project,.Name和.Save)。然后使用该接口或基类作为函数的类型,并且您将能够将两个类的集合传递给它。

答案 2 :(得分:1)

好, 据我所知,您希望添加“新”列表的类别/优先级,这些列表在存储库中不存在。

制作它。

public void SaveNewItems<T>(IList<string> newList, IList<T> currentList, string project)
    where T: new(), IStoreableItem
{
    //find only new items
    var toAdd = from itemName in newList
                where !currentList.Contains(i => i.Name = itemName)
                select new T {
                    Name = itemName,
                    Project = project
                };


    //find items to delete
    var toDelete = from item in currentList
                   where !newList.Contains(item.Name)
                   select item;

    toAdd.ToList().ForEach(item => item.Save());
    toDelete.ToList().ForEach(item => item.Delete());
}

Category和Prio必须从包含名称,项目和保存/删除方法的IStoreableItem派生。

答案 3 :(得分:0)

如果PriorityCategory都是从具有一组通用方法/属性的相同基类派生的,或者实现相同的接口,则可以。您只需要将PriorityCategory的特定引用替换为对该基类或接口的引用(如果适用)。

有一些次要的代码差异(比如第一个代码块中的List<string>(Categories)),您将不得不考虑如何处理,但是一旦祖先/接口问题,大多数代码都将落实到位已经解决了。

答案 4 :(得分:0)

我发现dynamic对于暴露相同属性的类型集非常有用,但是没有实现相同的接口。

使用foreach(dynamic d in myList)... d.Name...遍历列表,将其包装到方法中,并传递不同的IList<object>个实例(类别或优先级)。

需要C#4.0。

答案 5 :(得分:0)

你需要从同一个基类派生优先级和类别......然后你可以做以下几点:

public void ProcessLists<ItemType>(Func<int, IEnumerable<ItemType>> Loader) whereItemType : CommonBase, new() {
List<string> items = new List<string>();
IList<ItemType> currentItems = Loader(project.ID).ToList();
if (currentItems != null) {
    foreach (var existingItem in currentItems) {
        if (items.Contains(existingItem.Name))
            items.Remove(existingItem.Name);
        else
            existingItem.Delete(Services.UserServices.User);
    }
    foreach (string item in items) {
        ItemType item = new ItemType();
        item.Project = project
        item.Name = item.ToString();
        item.Save();
    }
}

}

当然,有些类型(例如project.ID)只是猜测,应该用适当的行代替。

您可以通过以下方式调用优先功能:

ProcessLists<Priority>(id => Priority.LoadForProject(project.ID));