Yazdığım projede Business işi yaptığım manager class da dto ve entityleri eşlemek için AutoMapper kullanıyorum. Dto ve Entityler i tek noktadan yönetiyorum.
Örneğin
public class GetTakvimDto : BaseTakvimDto, IMapFrom<Takvim>
{
public void Mapping(Profile profile)
{
profile.CreateMap<Takvim, GetTakvimDto>()
.ForMember(dest => dest.SatisAdedi, opt => opt.MapFrom(src => src.Tarifeler.Sum(x => x.TakvimKoltukTarifeler.Count(y => y.KayitDurumu == EntityStatus.ACTIVE && y.Biletler.Any(x => x.KayitDurumu == EntityStatus.ACTIVE)))))
}
}
Diğer örnekler ListTakvimDto, AddTakvimDto, UpdateTakvimDto …. takvim nesnesiyle yapacağım tüm crud operasyonlar için bir dto karşılığını bu şekilde ekliyorum. Extra operasyonlar için ise yine aynı yöntem ile devam ediyorum.
Örnekte dikkat ettiyseniz GetTakvimDto nesnesi doldurulurken artık satış adeti property sine labmda expression ile yazılan bir sum fonksiyonu değer üretecek ve onu bind edecek. Bu lambda expression içinde ki tüm şart ifadeleri statik veriler ile doluyor. Örneğin bir entity durumlarının karşılıklarının olduğu bir EntityStatus enum u var ve içinde ki bir parametre ACTIVE parametresi. kayıtdurumu aktif olan tüm kayıtlar toplanacak satısadeti propertysine bind edilecek.
Ama bunu peki business katmanından dinamik gelecek bir değerle yapmak istersek ne yapmamız gerekiyor. Yani automapper e dinamik parametre geçisi sağlayacağız.
O da şu şekilde;
public class GetTakvimDto : BaseTakvimDto, IMapFrom<Takvim>
{
public void Mapping(Profile profile)
{
profile.CreateMap<Takvim, GetTakvimDto>()
.ForMember(dest => dest.DahaOnceSecildiMi, opt => opt.MapFrom((src, dst, _, context) => src.TakvimKullanici.Any(x => x.FkKullaniciId == (int)context.Items["KullaniciId"])))
}
}
Öncelikle
Bir
takvim entity si,
kullanici entity si,
birde many to many ilişkiye sahip kullanıcının seçtiği takvimleri tutan takvimkullanici entitysi var
Takvimleri listelerken aynı kullanıcı daha önce seçtiği bir günü seçmesini engellemek için daha önce seçtiği ve kaydettiği günleri daha takvim listeleniyorken engellemek için dinamik olarak automapper içine dinamik olarak kullanıcıid parametresini geçmem gerekti.
public class GetTakvimDto seviyesinde geçerli bir context olmadığı için context üzerinden UserId ye ulaşmam mümkün değil,
ya da o katmanda aktif kullanıcı servisi inject edilemediği için
ya cache mekanizmasında tutacağım, ya da session da. Eee session nesneside geçerli bir context in olduğu bir katmanda değil. Tek alternatif cache de değil. Automapper a dinamik parametre geçişi ile daha efektiflik sağlayabiliriz.
Geriye tek kalan şey Business katmanından dto map leme işlemi yaptığım Dto katmanınına dinamik parametre geçmek. Peki bu nasıl yapılıyor ?
dtos = _mapper.Map<List<Takvim>, List<GetTakvimDto>>(entities, opt=> opt.Items["KullaniciId"] = aktifKullanici.Result.Result.Id );
KEY -VALUE pair ikilisi ile parametre geçebiliyoruz
opt=> opt.Items[“KullaniciId”] = aktifKullanici.Result.Result.Id
KEY > KullanıcıId
VALUE > aktifKullanici.Result.Result.Id
For member içinde
.ForMember(dest => dest.DahaOnceSecildiMi, opt => opt.MapFrom((src, dst, _, context) => src.TakvimKullanici.Any(x => x.FkKullaniciId == (int)context.Items["KullaniciId"])))
gönderilen KullaniciId parametresini dinamik şekilde okuyabiliriz. Bu şimdiye kadar anlatan teknik kod kısmı automapper 9 sürümü ile yapıldı.
Daha alt seviyede bir automapper sürümü ile çalışıyorsunuz tüm hikayeyi aşağıdaki kod ile uygulayabilirsiniz. Çünkü 8.0.0 sürümünden itibaren AutoMapper’ın API’si değiştirilmiştir. map context ine erişmek için kullanım (src, dst, _, context) şeklinde değiştirilmiştir.
Mapper.CreateMap<Source, Dest>()
.ForMember(d => dest.DahaOnceSecildiMi, opt => opt.ResolveUsing(res => res.Context.Options.Items["KullaniciId"]));
Mapper.Map<Source, Dest>(src, opt => opt.Items["KullaniciId"] = aktifKullanici.Result.Result.Id);
Diğer bir sürü soru cevap için
https://stackoverflow.com/questions/31748671/pass-objects-to-automapper-mapping adresine bakabilirsiniz.