2011-12-27 2 views
5

다음 두 메서드는 내 DB에서 데이터를 가져 와서 채워진 SelectList 개체 ("All"옵션 값 포함)를 반환하여 내보기로 전달합니다. 문제는 서로 다른 리포지토리 개체에 액세스하고 ID 이름 (StatusId 및 TeamId)이 다르다는 점과 거의 동일하다는 것입니다. 리파지토리를 매개 변수로 받아들이고 리다이렉션이나 람다 식을 사용하여 ID 이름이 무엇인지 파악하는 단일 메서드로 리팩토링 할 수있는 기회가 있다고 생각합니다. 이것을 달성하기 위해.하나의 메서드에 SelectList를 생성하는 두 개의 메서드를 리 팩터 처리합니다.

private SelectList GetStatusSelectList(int selectedStatusId) 
{ 
    List<MemberStatus> statusList = _memberStatusRepository.All().ToList(); 
    statusList.Insert(0, new MemberStatus {StatusId = 0, Name = "All"}); 
    var statusSelectList = new SelectList(statusList, "StatusId", "Name", selectedStatusId); 
    return statusSelectList; 
} 

private SelectList GetTeamSelectList(int selectedTeamId) 
{ 
    List<MemberTeam> teamList = _memberTeamRepository.All().ToList(); 
    teamList.Insert(0, new MemberTeam { TeamId = 0, Name = "All" }); 
    var teamSelectList = new SelectList(teamList, "TeamId", "Name", selectedTeamId); 
    return teamSelectList; 
} 

이러한 방법을 하나의 방법으로 리팩터링하는 방법을 알아낼 수 있습니까?

+1

이러한 클래스를 편집 할 수 있습니까? 즉 인터페이스를 추가 할 수 있습니까? –

+0

예 ... _memberTeamRepostiory와 _memberStatusRepository 모두 IRepository 인터페이스를 구현합니다. 이 인터페이스에는 주어진 TEntity의 _dbSet을 단순히 리턴하는 IQueryable All()과 같은 메소드를 포함하여 DB와 상호 작용하는 모든 메소드가 있습니다. – bigmac

+0

MemberTeam과 MemberStatus는 직접 또는 부분 클래스로 수정할 수 있습니까? – foson

답변

2

는 다음을 시도 할 수 있습니다 :

private SelectList GetStatusSelectList(int selectedStatusId) 
{ 
    return GetGenericSelectList<MemberStatus>(selectedStatusId, _memberStatusRepository.All().ToList(), "StatusId"); 
} 

private SelectList GetTeamSelectList(int selectedTeamId) 
{ 
    return GetGenericSelectList<MemberTeam>(selectedTeamId, _memberTeamRepository.All().ToList(), "TeamId"); 
} 

private SelectList GetGenericSelectList<T>(int selectedTeamId, List<T> list, string idFieldName) where T : new() 
{ 
    var firstItem = new T(); 
    (firstItem as dynamic).Name = "All"; 
    var l = new List<T>(list); 
    l.Insert(0, firstItem); 
    return new SelectList(l, idFieldName, "Name", selectedTeamId); 
} 

이 솔루션은 적합하지 않습니다 어떤 규칙에 의존한다 (예를 들어, 모든 항목 Name 속성을 가져야한다). 그러나 그것은 시작하는 나쁜 방법이 아닌 것 같습니다. 속성 이름 대신 표현식을 사용하면 컴파일 시간을 확인하면서 속성 이름을 변경할 수 있습니다.

+0

코드를 제공해 주셔서 감사합니다. 이것은 효과가있는 것 같지만 두 가지 질문이 있습니다. 먼저, 코드의 3 번째와 4 번째 줄을 제거하고 대신 'list.Insert (0, firstItem)'을 사용했습니다. 이 문제가 있습니까? 둘째, 나는 T : new()가 메소드 서명에서 의미하는 것이 무엇인지 모른다. 이 일이 무엇인지 알려 주실 수 있습니까? – bigmac

+0

인자로 새로운리스트를 만듭니다. 그렇지 않으면 기존리스트가 수정 될 것입니다 (기존리스트를 넘겨 주면 함수는 그것에 새로운 원소를 삽입합니다). 그게 문제가되지 않을 수도 있지만 원래 목록이이 방법 옆의 다른 곳에서 사용된다면 어떨까요? 새로운 제약에 관해서는'new T()'만 할 수 있습니다. 자세한 내용은 http://msdn.microsoft.com/en-us/library/sd2w2ew5.aspx를 참조하십시오. –

+1

이것은 즉각적인 필요를 충족시키는 가장 깨끗한 해결책입니다. 감사합니다. the_joric! – bigmac

3

글쎄, 내가 생각해 볼 수있는 가장 일반적인 내용이지만, MemberStatusMemberTeamIIdentifiable을 구현해야하며, 귀하의 사례에 적용 할 수 있는지 여부는 알 수 없습니다. 그렇다면, 이것이 갈 길이 될 것입니다.

private SelectList GetList<T>(IRepository repository, int id, string name) 
    where T : IIdentifiable, new() 
{ 
    List<IIdentifiable> list = repository.All().ToList(); 
    list.Insert(0, new T() { Name = name, Id = id }); 
    var statusSelectList = new SelectList(list, "Id", "Name", id); 
} 

그리고 내가 무엇을보고에서 인터페이스 코드

interface IIdentifiable 
{ 
    int Id { get; set; } 
    string Name { get; set; } 
} 
+0

감사합니다. 하나의 관심사, MemberTeam 및 MemberStatus에 대한 내 POCO 개체는 매우 간단하며 둘 다 Name 속성이 있지만 각 Id 속성 (StatusId 및 TeamId)에 대한 고유 한 이름이 있습니다. 이러한 속성을 그대로 유지하고 설명하는 인터페이스를 구현하는 방법이 있습니까? DB 디자인에 대해 더 잘 설명하는 이름을 선호하는 경향이 있지만 권장되는 경우 더 일반적인 ID 필드를 사용하도록 설득 할 수 있습니다. – bigmac

+0

물론, 클래스의'StatusId'와'TeanId'에'IIdentifiable.Id' 속성을 매핑하면됩니다. 'int Id {get {return StatusId; } set {StautsId = value; }}'당신의'MemberStatus' 클래스에서. 이게 효과가 없을까요? –

+1

@ 토미 슬라브 ... 고맙습니다. 비슷한 것을 게시 한 Foson에 언급했듯이 도메인 모델을보다 강력하게 리팩토링하기 위해 메서드를 사용 하겠지만 the_joric의 대답은 내가 게시 한 질문에 대해 가장 간결하므로 그의 게시물을 수락 할 것입니다 . 그러나 다시 한 번 의견을 보내 주셔서 감사 드리며이 프로젝트를 계속 진행하면서 새로운 방향을 제시해 주셨습니다. – bigmac

1

는 하나의 방법으로이 리팩토링의 방법으로 주요 장애물은 권리를 결정하는 이외에, new MemberStatusnew MemberTeam 전화입니다 사용할 저장소.

우아한 솔루션을 내놓으려면 인프라를 좀 더 구성해야합니다. 기본적으로 유형에 따라 올바른 저장소를 해결해야하며 개체 인스턴스를 빌드하는 일종의 팩토리가 필요합니다.

다음은 하나의 메소드에 코드를 리팩토링, 그러나 (내 생각에)없는 것 별도의 방법보다 더 좋은 당신은 이미 :

private SelectList GetSelectList<T>(int selectedId, Func<List<T>> repoAllFunc, Func<T> typeNewFunc, string idName) 
{ 
    List<T> list = repoAllFunc(); 
    list.Insert(0, typeNewFunc()); 
    var selectList = new SelectList(list, idName, "Name", selectedId); 
    return selectList; 
} 

그런 다음이처럼 호출 할 수

+0

Ethan, 나는 당신의 코드도 시도하고 있지만, 당신의 방법을 호출하는 방법을 생각해내는 데 힘든 시간을 보냈습니다. 나는 그것이 람다 표현식을 취한다고 가정하지만, 이것들에 익숙하지 않기 때문에, Func <> 매개 변수를 전달하는 것에 대한 포인터를 나에게 줄 수 있습니까? – bigmac

+0

@bmccleary 사용 방법에 대한 예제를 추가했습니다. 이 예제의 함수는 매개 변수를 사용하지 않으므로 구문은 대리자 구문 에서처럼 간단합니다. 그렇지 않으면 조금 어색해집니다. –

+0

샘플 코드 및 설명에 감사드립니다. 지금 당장은 the_joric의 대답을 받아 들일 것입니다. 즉각적인 필요를 위해 좀 더 깔끔하게 처리 할 수 ​​있지만, 잠깐 동안 대리자를 메서드에 전달하는 방법을 알아 내려고 노력하고 있으며, 샘플에서이 작업을 수행하는 방법에 대한 지침을 제공합니다. 내 코드의 다른 영역, 정말 고마워요! – bigmac

0

IRepository에 몇 가지 "기능"이 추가되면 더 깨끗한 코드가 생성됩니다.

All() 대신 첫 번째 두 줄을 처리하는 방법이 SingleRecordsWithAllRecord()입니다. 그런 다음 저장소에 자체 DataValueFieldDataTextField을 정의하게하십시오.

private SelectList GetSelectList(IRepository repo, int selectedId) 
{ 
    var selectListAll = repo.SingleRecordsWithAllRecord().ToList(); 

    return new SelectList(selectListAll, 
         repo.DataValueField, 
         repo.DataTextField, 
         selectedId); 
} 
+0

오스틴, 나는 여기서 당신의 생각 패턴을 좋아합니다. 나는 코드를 계속 사용하면서 그것을 시도 할 것이라고 생각합니다. 그러나 지금은 the_joric의 대답은 제 필요에 가장 직접적이었습니다. 의견을 보내 주셔서 감사합니다! – bigmac

1

당신은 미친 약간의 인터페이스를 가서 다음을 수행 할 수 있습니다

using System; 
using System.Collections.Generic; 
using System.Linq; 

namespace ConsoleApplication3 
{ 

    public class MemberStatus : IDefault<MemberStatus> 
    { 
     public int StatusId { get; set; } 
     public string Name { get; set; } 

     public MemberStatus Default 
     { 
      get { return new MemberStatus() { StatusId = 0, Name = "All" }; } 
     } 

     public string IdName 
     { 
      get { return "StatusId"; } 
     } 
    } 

    public class MemberTeam : IDefault<MemberTeam> 
    { 
     public int TeamId { get; set; } 
     public string Name { get; set; } 

     public MemberTeam Default 
     { 
      get { return new MemberTeam() { TeamId = 0, Name = "All" }; } 
     } 

     public string IdName 
     { 
      get { return "TeamId"; } 
     } 
    } 

    public interface IDefault<T> 
    { 
     T Default { get; } 
     string IdName { get; } 
    } 

    public interface IRepository<T> 
    { 
     IEnumerable<T> All(); 
    } 

    public class MemberStatusRepository : IRepository<MemberStatus> 
    { 
     public IEnumerable<MemberStatus> All() 
     { 
      return new[] { 
       new MemberStatus(), 
       new MemberStatus() 
      }; 
     } 
    } 
    public class MemberTeamRepository : IRepository<MemberTeam> 
    { 
     public IEnumerable<MemberTeam> All() 
     { 
      return new[] { 
       new MemberTeam(), 
       new MemberTeam() 
      }; 
     } 
    } 

    public class DataAccessLayer 
    { 
     IRepository<MemberStatus> _memberStatusRepository; 
     IRepository<MemberTeam> _memberTeamRepository; 
     public DataAccessLayer() 
     { 
      _memberStatusRepository = new MemberStatusRepository(); 
      _memberTeamRepository = new MemberTeamRepository(); 
     } 


     public SelectList<TResult> GetTeamSelectList<TRepository, TResult>(TRepository repo, int selectedTeamId) 
      where TRepository : IRepository<TResult> 
      where TResult : IDefault<TResult>, new() 
     { 
      List<TResult> teamList = repo.All().ToList(); 
      var dummyobj = new TResult(); 
      teamList.Insert(0, dummyobj.Default); 
      var teamSelectList = new SelectList<TResult>(teamList, dummyobj.IdName, "Name", selectedTeamId); 
      return teamSelectList; 
     } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      var dal = new DataAccessLayer(); 
      SelectList<MemberStatus> results = dal.GetTeamSelectList<IRepository<MemberStatus>, MemberStatus>(new MemberStatusRepository(), 5); 
      Console.WriteLine(); 
      Console.Read(); 
     } 
    } 

    public class SelectList<TResult> 
    { 
     public SelectList(List<TResult> teamList, string p, string p_2, int selectedTeamId) 
     { 

     } 
    } 

} 

당신이 인터페이스의 정적 속성을 정의 할 수 있다면 좋을 텐데,하지만 당신은 내가 더미 객체를 생성에 의존 할 수 없기 때문에 대신.

+0

@foson ... 와우! 모든 코드를 가져 주셔서 감사합니다. 여기서 당신이 어디로 향하고 있는지 알 수 있습니다. 나는 도메인 클래스에 약간의 리팩토링을하여 방법론을 채택하려고 노력할 수도 있다고 생각하지만, 지금 당장은 the_joric의 대답이 당면한 문제를 해결하는 가장 기본적인 방법이었습니다. 그것을 받아 들인다. 하지만 다시 한 번 당신의 코드를 참고서로 사용하여 가까운 장래에 좀 더 무거운 리팩터링을 할 수있게 해드립니다. 시간과 세부 사항에 대해 대단히 감사합니다! – bigmac

+0

NP. 내가 말했듯이, 내 솔루션은 약간의 인터페이스가 미친다. 확실히 동적 인 것보다 복잡하거나 덜 읽기 쉽다. 다이나믹 또는 리플렉션을 사용하는 경우 개인적으로 솔루션이 필자의 수용 가능한 예상 내에 있는지 확인하기 위해 일부 퍼포먼스 테스트를 수행해야합니다. – foson

관련 문제