2011-12-27 21 views
5

bir SelectList oluşturmak yöntemleri I Sonra Bence üzerine geçmek zaman DB veri almak ve (bir "tüm" seçeneği da dahil) bir doldurulan SelectList nesnesi geri aşağıdaki iki yöntem vardır. Sorun, bunların hem farklı depo nesnelerine erişimlerinin hem de farklı ID adlarına (StatusId ve TeamId) sahip olmaları istisnasıyla neredeyse aynı olmalarıdır. Ben bir parametre olarak depo kabul eder ve her nasılsa kimlik adı belki yansıması veya lambda ifadesi çeşit kullanarak, ne olması gerektiğini anlamadan tek yöntem haline bunları refactor için bir fırsat olduğunu düşünüyorum, ama oldukça bilmiyorum Bunu gerçekleştirmek için.Refactor İkisi, tek bir yöntem

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; 
} 

Bunların nasıl tek bir yöntemle yeniden düzenleneceğini anlamaya yardımcı olan var mı?

+1

Bu sınıfları düzenleyebilir misiniz, arayüz ekleyebilir misiniz? –

+0

Evet ... hem _memberTeamRepostiory hem de _memberStatusRepository, bir IRepository arabirimini uygular. Bu arabirim, DB ile etkileşime girecek tüm yöntemlere sahiptir ve IQueryable Tümü() ile birlikte verilen TEntity'nin _dbSet'ini döndürür. – bigmac

+0

Nasıl MemberTeam ve MemberStatus hakkında - bunları doğrudan veya kısmi sınıflarla değiştirebilir misiniz? – foson

cevap

2

aşağıdaki deneyebilirsiniz:

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

Bu çözüm ideal değildir ve bazı sözleşmeler dayanır (örneğin tüm öğeleri Name özelliğine sahip olmalıdır). Ancak başlamak için kötü bir yol gibi görünüyor. Özellik isimleri yerine İfadeler kullanılarak daha fazla geliştirilebilir - bu özellik, derleme zamanı denetimi ile özellik adlarının değiştirilmesine izin verir.

+0

Kod için teşekkürler. Bu işe yarıyor gibi görünüyor, ama senin için iki sorum var. İlk olarak, kodunuzun 3. ve 4. satırlarını kaldırdım ve bunun yerine 'list.Insert (0, firstItem)' kullandım. Bununla ilgili herhangi bir sorun var mı? İkinci olarak, “T: new()” ifadesinin, yöntem imzasında ne anlama geldiğini bilmiyorum. Bunun ne yaptığını bana bildirir misin? – bigmac

+0

Argümandan yeni bir liste oluşturuyorum çünkü mevcut liste değiştirilecek (mevcut bir listeyi geçirdiğinizde fonksiyon buna yeni bir eleman ekler). Bu bir sorun olmayabilir, ancak bu orijinal yöntem bu yöntemin yanında başka bir yerde kullanılıyorsa ne olur? Yeni kısıtlama ile ilgili olarak - sadece yeni T() 'nin yapılmasına izin verir. Daha fazla bilgi için http://msdn.microsoft.com/en-us/library/sd2w2ew5.aspx adresine bakın. –

+1

Bu, acil ihtiyaçlarim için en temiz çözüm, bu yüzden teşekkür ederim the_joric! – bigmac

3

Eh, bu şimdiye kadar gelebilir en genel, ama senin durumunda uygulayabileceğiniz eğer MemberStatus ve MemberTeam Bilmiyorum IIdentifiable uygulamak gerektirecektir. Eğer öyleyse, bu gitmek için bir yol olurdu.

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

Ve gördüğüm kadarıyla arayüz kodu

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

Teşekkürler Tomislav. Bir endişe olsa da, MemberTeam ve MemberStatus için benim POCO nesneler çok basittir ve her ikisi de bir Name özelliğine sahiptir, ancak her birinin Id özelliği (StatusId ve TeamId) için benzersiz bir adı vardır. Bu özellikleri olduğu gibi adlandırmak ve hala tanımladığınız arabirimi uygulamak için bir yolu var mı? Adın DB tasarımı için daha açıklayıcı olmasından hoşlanıyorum, ancak tavsiye edilirse daha genel bir kimlik alanı kullanmaya ikna edilebilir. – bigmac

+0

Elbette, sadece IIdentifiable.Id' özelliğini sınıflarınızdaki 'StatusId' ve' TeanId' ile eşleyin. int id {get {return StatusId; } set {StautsId = değer; }} '' ÜyeStatus 'sınıfınızda. Bu işe yaramaz mı? –

+1

@ Tomislav ... bunun için teşekkürler. Benzer bir şey gönderen foson'dan bahsettiğim gibi, etki alanı modelimin daha sağlam bir şekilde yeniden yapılandırılması için yönteminizi kullanacağım, ancak yayınladığım soru için en iyi cevap, bu gönderiyi kabul edeceğim. . Ama yine de, giriş için teşekkür ederim ve bu projeyi oluşturmaya devam ederken bana biraz yeni yön gösterdiniz! – bigmac

1

, tek bir yöntem içine bu üstlenmeden yolunda ana engeller hakkı belirlenmesine ek olarak, new MemberStatus ve new MemberTeam aramalar Kullanılacak depo.

Zarif bir çözüm bulmak için, biraz daha fazla altyapı yapılandırmanız gerekir - temel olarak türüne göre doğru depoyu çözmeniz gerekir ve bir çeşit fabrikada nesne örneğini oluşturmak istersiniz.

şu tek yöntem haline kodunu refactor ama (Bence) değil edecek ayrı yöntemlerden daha iyi zaten var:

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; 
} 

Sonra böyle diyebiliriz:

var memberStatusSelectList = 
    GetSelectList<MemberStatus>(
     id, 
     () => _memberStatusRepository.All().ToList(), 
     () => new MemberStatus {StatusId = 0, Name = "All"}); 
+0

Ethan, Kodunuzu da deniyorum, ancak yönteminizi nasıl arayacağınızı anlamak için zor bir zaman geçiriyorum. Bir lambda ifadesi aldığını sanıyorum, ama bunlardan yeni olduğum için, Func <> parametreleri için ne geçtiğime dair bir işaretçi verebilir misiniz? – bigmac

+0

@bmccleary Nasıl kullanacağına bir örnek ekledim. Bu örnekteki işlevler, hiçbir sözdizimi almaz, bu nedenle sözdizimi, temsilci sözdizimi için aldığı kadar basittir. Aksi halde, biraz daha çirkinleşirler. –

+0

Örnek kod ve açıklama için teşekkür ederiz. Şu anki ihtiyacım için küçük bir temizleyici olduğu için, şu anki yanıtı kabul edeceğim, ancak bir süredir delegeleri bir süreye nasıl aktarılacağını anlamaya çalışıyorum ve örneğiniz bunun nasıl yapılacağı konusunda bana bir yön veriyor. kodumun diğer alanları, çok teşekkür ederim! – bigmac

0

IRepository bazı "özellikler" eklerse, bazı temiz kodlar alırsınız.

yerine All()

ilk iki satır işleyen bir SingleRecordsWithAllRecord() yöntemi vardır. Sonra depo DataValueField ve DataTextField kendi tanımlamak gerekir.

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

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

Austin, Düşünce düzeninizi burada seviyorum ve bence kodla devam ederken bunu deneyeceğim, fakat şimdilik, thejor'un cevabı en acil ihtiyaçlardı. Giriş için teşekkürler! – bigmac

1

Deli biraz arayüze gidip yapın yapabilirsiniz:

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) 
     { 

     } 
    } 

} 

bir arayüzde statik özelliklerini tanımlamak eğer iyi olurdu, ancak ben bir kukla nesnesi oluşturarak güvenemez beri yerine.

+0

@foson ... WOW! Tüm kodlar için teşekkürler. Burada nereye gittiğinizi görebiliyorum ve sanırım benim metodolojimi benimsemek için alan sınıfımın biraz yeniden düzenlenmesi üzerinde çalışabilirim, ama şimdilik, en yakın cevap, acil ihtiyaçlara cevap vermenin en temel yoluydu. kabul etmek. Ama yine de, kodunuzu referans olarak saklıyorum, böylece yakın gelecekte daha ağır bir refactoring üzerinde çalışabilirim, bu yüzden zaman ve detaylarınız için çok teşekkür ederim! – bigmac

+0

NP. Söylediğim gibi, benim çözümüm biraz çılgın bir arayüzdür - dinamik kullanmaktan kesinlikle daha karmaşık/daha az okunabilir. Dinamik veya yansıma kullanıyor olsaydım, çözümün benim kabul edilebilir mükemmel beklentilerim içinde olmasını sağlamak için bazı mükemmel testler yapardım. – foson

İlgili konular