यह पहली बार है जब मैं एक और अधिक डोमेन संचालित डिजाइन दृष्टिकोण लागू कर रहा हूं। मैंने Onion Architecture को आजमाने का निर्णय लिया है क्योंकि यह आधारभूत संरचना/प्लेटफॉर्म/आदि के बजाय डोमेन पर केंद्रित है।प्याज वास्तुकला, कार्य इकाई और एक सामान्य रिपोजिटरी पैटर्न
आदेश में इकाई की रूपरेखा से दूर सार करने के लिए, मैं काम कार्यान्वयन का एक यूनिट के साथ एक सामान्य भंडार बनाया है।
IRepository<T>
और IUnitOfWork
इंटरफेस:
IRepository<T>
की public interface IRepository<T>
{
void Add(T item);
void Remove(T item);
IQueryable<T> Query();
}
public interface IUnitOfWork : IDisposable
{
void SaveChanges();
}
इकाई की रूपरेखा कार्यान्वयन और IUnitOfWork
:
public class EntityFrameworkRepository<T> : IRepository<T> where T : class
{
private readonly DbSet<T> dbSet;
public EntityFrameworkRepository(IUnitOfWork unitOfWork)
{
var entityFrameworkUnitOfWork = unitOfWork as EntityFrameworkUnitOfWork;
if (entityFrameworkUnitOfWork == null)
{
throw new ArgumentOutOfRangeException("Must be of type EntityFrameworkUnitOfWork");
}
dbSet = entityFrameworkUnitOfWork.GetDbSet<T>();
}
public void Add(T item)
{
dbSet.Add(item);
}
public void Remove(T item)
{
dbSet.Remove(item);
}
public IQueryable<T> Query()
{
return dbSet;
}
}
public class EntityFrameworkUnitOfWork : IUnitOfWork
{
private readonly DbContext context;
public EntityFrameworkUnitOfWork()
{
this.context = new CustomerContext();;
}
internal DbSet<T> GetDbSet<T>()
where T : class
{
return context.Set<T>();
}
public void SaveChanges()
{
context.SaveChanges();
}
public void Dispose()
{
context.Dispose();
}
}
ग्राहक भंडार:
public interface ICustomerRepository : IRepository<Customer>
{
}
public class CustomerRepository : EntityFrameworkRepository<Customer>, ICustomerRepository
{
public CustomerRepository(IUnitOfWork unitOfWork): base(unitOfWork)
{
}
}
ASP.NET MVC नियंत्रक भंडार का उपयोग करते हुए:
container.RegisterType<IUnitOfWork, EntityFrameworkUnitOfWork>();
container.RegisterType<ICustomerRepository, CustomerRepository>();
समाधान::
समस्याओं
public class CustomerController : Controller
{
UnityContainer container = new UnityContainer();
public ActionResult List()
{
var unitOfWork = container.Resolve<IUnitOfWork>();
var customerRepository = container.Resolve<ICustomerRepository>();
return View(customerRepository.Query());
}
[HttpPost]
public ActionResult Create(Customer customer)
{
var unitOfWork = container.Resolve<IUnitOfWork>();
var customerRepository = container.Resolve<ICustomerRepository>();;
customerRepository.Add(customer);
unitOfWork.SaveChanges();
return RedirectToAction("List");
}
}
एकता के साथ निर्भरता इंजेक्शन?
रिपोजिटरी कार्यान्वयन (ईएफ कोड) बहुत सामान्य है। यह सब
EntityFrameworkRepository<T>
वर्ग के पक्ष में बैठता है। कंक्रीट मॉडल भंडार में इस तर्क में से कोई भी शामिल नहीं है। यह मुझे अनावश्यक कोड लिखने से बचाता है, लेकिन संभवतः लचीलापन बलिदान देता है?ICustomerRepository
औरCustomerRepository
कक्षाएं मूल रूप से खाली हैं। वे पूरी तरह से अमूर्तता प्रदान करने के लिए वहाँ हैं। जहां तक मैं समझता हूं, यह प्याज आर्किटेक्चर की दृष्टि से फिट बैठता है, जहां बुनियादी ढांचे और मंच-निर्भर कोड आपके सिस्टम के बाहर बैठते हैं, लेकिन खाली कक्षाएं और खाली इंटरफेस होने पर गलत लगता है?एक अलग दृढ़ता कार्यान्वयन (Azure टेबल संग्रहण कहें) का उपयोग करने के लिए, फिर एक नया
CustomerRepository
कक्षा बनाने की आवश्यकता होगी औरAzureTableStorageRepository<T>
का उत्तराधिकारी होगा। लेकिन इससे अनावश्यक कोड (एकाधिक ग्राहक रिपोर्ट) हो सकता है? यह प्रभाव मजाक कैसे करेगा?एक अन्य कार्यान्वयन (Azure टेबल संग्रहण कहें) में अंतर्राष्ट्रीय समर्थन पर सीमाएं हैं, इसलिए AzureTableStorageUnitOfWork क्लास इस संदर्भ में काम नहीं करेगी।
वहाँ जिस तरह से मैंने यह किया है के साथ किसी भी अन्य मुद्दों कर रहे हैं?
(मैं this post से मेरी प्रेरणा के सबसे ले लिया है)
आप आईओसी कंटेनर पर निर्भरता लेकर [सेवा लोकेटर एंटी-पैटर्न] (http://blog.ploeh.dk/2010/02/03/ServiceLocatorisanAnti-Pattern/) का उपयोग कर रहे हैं। इसके बजाय, आपको अपने नियंत्रक में इंजेक्ट करने के लिए एक फैक्ट्री क्लास पंजीकृत करनी चाहिए। कुछ आईओसी कंटेनर आपके लिए इनमें से एक को 'Func' निर्भरता –
AlexFoxGill