代码之家  ›  专栏  ›  技术社区  ›  JoseMarmolejos

合并这两种非常相似的方法

  •  1
  • JoseMarmolejos  · 技术社区  · 14 年前

    public Offer GetOffer(int id, string languageCode = Website.LanguageSettings.DefaultLanguageCode)
            {
                Entities.Offer offerEntity = _db.Offers.FirstOrDefault(offer => offer.Id == id);
    
                if (languageCode.ToLower(CultureInfo.InvariantCulture) != Website.LanguageSettings.DefaultLanguageCode)
                {
                    using (IDocumentSession session = store.OpenSession())
                    {
                        Translation.Offer translatedOffer = session.LuceneQuery<Translation.Offer>(Website.RavenDbSettings.Indexes.Offers)
                            .Where(string.Format("ObjectId:{0} AND LanguageCode:{1}", id, languageCode))
                            .OrderByDescending(offer => offer.Id)
                            .FirstOrDefault();
    
                        var offerPOCO = Mapper.DynamicMap<Translation.Offer, Offer>(translatedOffer);
                        offerPOCO.Id = offerEntity.Id;
    
                        return offerPOCO;
                    }
                }
    
                return Mapper.Map<Entities.Offer, Offer>(offerEntity);
            }
    

    以及

    public Hotel GetHotel(int id, string languageCode = Website.LanguageSettings.DefaultLanguageCode)
            {
                Entities.Hotel hotelEntity = _db.Hotels.FirstOrDefault(hotel => hotel.Id == id);
    
                if (languageCode.ToLower(CultureInfo.InvariantCulture) != Website.LanguageSettings.DefaultLanguageCode)
                {
                    using(IDocumentSession session = store.OpenSession())
                    {
                        Translation.Hotel translatedHotel = session.LuceneQuery<Translation.Hotel>(Website.RavenDbSettings.Indexes.Hotels)
                            .Where(string.Format("ObjectId:{0} AND LanguageCode:{1}", id, languageCode))
                            .OrderByDescending(hotel => hotel.Id)
                            .FirstOrDefault();
    
                        Hotel hotelPOCO = Mapper.DynamicMap<Translation.Hotel, Hotel>(translatedHotel);
                        hotelPOCO.Id = hotelEntity.Id;
    
                        return hotelPOCO;
                    }
                }
    
                return Mapper.Map<Entities.Hotel, Hotel>(hotelEntity);
            }
    

    它们在大多数方面都完全相同:它们采用相同的参数、构建相同的查询并执行相同的操作,唯一不同的是它们处理和输出的对象的类型。除了构建一个方法来生成Where()param字符串之外,我想不出任何方法可以将此代码的大部分(或全部)合并到一个方法中,然后从GetOffer()和GetHotel()方法调用它,因为我将得到更多类似这两个方法的代码。

    任何建议都非常感谢。

    编辑:添加解决方案,以便如果另一个可怜的灵魂遇到这个问题,他/她可以有一个起点:

    private TReturn GetObject<TReturn, TEntity, TTranslation>(int id, string languageCode, string ravenDbIndex) where TEntity:EntityObject 
                                                                                                                        where TTranslation:Translation.BaseTranslationObject
                                                                                                                        where TReturn:BasePOCO
            {
                // TODO Run more tests through the profiler
                var entities = _db.CreateObjectSet<TEntity>();
                var entityKey = new EntityKey(_db.DefaultContainerName + "." + entities.EntitySet.Name, "Id", id); // Sticking to the Id convention for the primary key
                TEntity entity = (TEntity)_db.GetObjectByKey(entityKey);
    
                if(languageCode.ToLower(CultureInfo.InvariantCulture) != Website.LanguageSettings.DefaultLanguageCode)
                {
                    using(IDocumentSession session = store.OpenSession())
                    {
                        TTranslation translatedObject = session.LuceneQuery<TTranslation>(ravenDbIndex)
                            .Where(string.Format("ObjectId:{0} AND LanguageCode:{1}", id, languageCode))
                            .OrderByDescending(translation => translation.Id)
                            .FirstOrDefault();
    
                        TReturn poco = Mapper.DynamicMap<TTranslation, TReturn>(translatedObject);
                        poco.Id = id;
    
                        return poco;
                    }
                }
    
                return Mapper.Map<TEntity, TReturn>(entity);
            }
    

    GetObject<Hotel, Entities.Hotel, Translation.Hotel>(id, languageCode, Website.RavenDbSettings.Indexes.Hotels);
    

    每当我需要旅馆的时候。

    谢谢大家的回复,从他们身上学到了很多。

    3 回复  |  直到 14 年前
        1
  •  6
  •   Russ Cam    14 年前

    看起来您可以将其重构为泛型方法。类似的东西(我对重构一些方法调用的能力做了一些假设,但希望你能理解)

    public T Get<T>(int id, string languageCode = Website.LanguageSettings.DefaultLanguageCode)
            {
                Entity<T> entity = _db<T>.FirstOrDefault(entity => entity.Id == id);
    
                if (languageCode.ToLower(CultureInfo.InvariantCulture) != Website.LanguageSettings.DefaultLanguageCode)
                {
                    using(IDocumentSession session = store.OpenSession())
                    {
                        Translation<T> translatedEntity = session.LuceneQuery<Translation<T>>(Website.RavenDbSettings.Indexes.Entities<T>)
                            .Where(string.Format("ObjectId:{0} AND LanguageCode:{1}", id, languageCode))
                            .OrderByDescending(entity=> entity.Id)
                            .FirstOrDefault();
    
                        T POCO = Mapper.DynamicMap<Translation<T>, T>(translatedEntity);
                        POCO.Id = entity.Id;
    
                        return POCO;
                    }
                }
    
                return Mapper.Map<Entities<T>, T>(Entity);
            }
    
        2
  •  1
  •   p.campbell    14 年前

    Do One Thing - Single Responsibility Principle .

    的确,他们在工作中实现了相同的策略,但我建议,如果您将它们合并/重构为一个策略,那将比从中获益更令人困惑。

    考虑业务逻辑更改的可能性。一个会比另一个更不稳定吗?实现这一点是否与 GetFlights() GetCarRentals()

    我意识到,当使代码相同,并且可能在方法之间复制/粘贴/调整代码时,您会感觉到可以减少代码行,并且不会重复自己。我同样重视SRP和DRY,但在这种情况下,我更愿意为每个实体阅读和维护不同的方法 Offer , Hotel 等等。

        3
  •  0
  •   Jimmy Hoffa    14 年前

    GetDalObject(db => db.Hotels.FirstOrDefault(hotel => hotel.Id == id), ...
    

    然后你可以在hotel或offer等之间的调用中交换它,但是在你的情况下,我不知道这能有多大帮助,因为我认为sig会变得很糟糕,所以我会考虑在offer类型和hotel类型中实现变量部分,你可以通过一个接口访问,然后将Offer/Hotel类交给此方法。

    public interface ICommonDalObject
    {
        public string LuceneQueryString { get; }
        public ITranslation GetTranslation();
    }