मैंने पाया कि जो कुछ भी किया गया था, ईएफ को सार्वजनिक होने के लिए ICollection<T>
की आवश्यकता है। मुझे लगता है कि ऐसा इसलिए है क्योंकि जब डेटाबेस डेटाबेस से लोड होते हैं, तो मानचित्रण संग्रह संपत्ति की तलाश करता है, संग्रह प्राप्त करता है और फिर प्रत्येक बच्चे ऑब्जेक्ट्स को जोड़ने के लिए संग्रह के Add
विधि को कॉल करता है।
मैं यह सुनिश्चित करना चाहता था कि अतिरिक्त ऑब्जेक्ट पर एक विधि के माध्यम से जोड़ा गया था, इसलिए संग्रह को लपेटने का एक समाधान बनाया गया, जोड़ को पकड़कर और इसे मेरी पसंदीदा विधि में निर्देशित किया गया।
List
और अन्य संग्रह प्रकारों को विस्तारित करना संभव नहीं था क्योंकि Add
विधि वर्चुअल नहीं है। एक विकल्प Collection
वर्ग का विस्तार करना और InsertItem
विधि को ओवरराइड करना है।
मैं केवल उन लोगों के रूप ICollection<T>
इंटरफ़ेस का Add
, Remove
, और Clear
कार्यों पर ध्यान केंद्रित किया है जो कि संग्रह को संशोधित कर सकते हैं।
पहला, मेरा बेस संग्रह रैपर है जो ICollection<T>
इंटरफ़ेस लागू करता है डिफ़ॉल्ट व्यवहार सामान्य संग्रह का होता है। हालांकि, कॉलर कॉल करने के लिए वैकल्पिक Add
विधि निर्दिष्ट कर सकता है। इसके अलावा, कॉलर Add
, Remove
, Clear
संचालन को null
पर विकल्पों को सेट करके अनुमति नहीं दे सकता है। यदि कोई भी विधि का उपयोग करने का प्रयास करता है तो इसका परिणाम NotSupportedException
में फेंक दिया जाता है।
अपवाद की फेंकना उतना अच्छा नहीं है जितना कि पहले स्थान पर पहुंच को रोकना। हालांकि, कोड का परीक्षण किया जाना चाहिए (इकाई परीक्षण) और एक अपवाद बहुत जल्दी मिलेगा और उपयुक्त कोड परिवर्तन किया जाएगा।
public abstract class WrappedCollectionBase<T> : ICollection<T>
{
private ICollection<T> InnerCollection { get { return GetWrappedCollection(); } }
private Action<T> addItemFunction;
private Func<T, bool> removeItemFunction;
private Action clearFunction;
/// <summary>
/// Default behaviour is to be like a normal collection
/// </summary>
public WrappedCollectionBase()
{
this.addItemFunction = this.AddToInnerCollection;
this.removeItemFunction = this.RemoveFromInnerCollection;
this.clearFunction = this.ClearInnerCollection;
}
public WrappedCollectionBase(Action<T> addItemFunction, Func<T, bool> removeItemFunction, Action clearFunction) : this()
{
this.addItemFunction = addItemFunction;
this.removeItemFunction = removeItemFunction;
this.clearFunction = clearFunction;
}
protected abstract ICollection<T> GetWrappedCollection();
public void Add(T item)
{
if (this.addItemFunction != null)
{
this.addItemFunction(item);
}
else
{
throw new NotSupportedException("Direct addition to this collection is not permitted");
}
}
public void AddToInnerCollection(T item)
{
this.InnerCollection.Add(item);
}
public bool Remove(T item)
{
if (removeItemFunction != null)
{
return removeItemFunction(item);
}
else
{
throw new NotSupportedException("Direct removal from this collection is not permitted");
}
}
public bool RemoveFromInnerCollection(T item)
{
return this.InnerCollection.Remove(item);
}
public void Clear()
{
if (this.clearFunction != null)
{
this.clearFunction();
}
else
{
throw new NotSupportedException("Clearing of this collection is not permitted");
}
}
public void ClearInnerCollection()
{
this.InnerCollection.Clear();
}
public bool Contains(T item)
{
return InnerCollection.Contains(item);
}
public void CopyTo(T[] array, int arrayIndex)
{
InnerCollection.CopyTo(array, arrayIndex);
}
public int Count
{
get { return InnerCollection.Count; }
}
public bool IsReadOnly
{
get { return ((ICollection<T>)this.InnerCollection).IsReadOnly; }
}
public IEnumerator<T> GetEnumerator()
{
return InnerCollection.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return InnerCollection.GetEnumerator();
}
}
यह देखते हुए कि बेस क्लास हम इसे दो तरीकों से उपयोग कर सकते हैं। उदाहरण मूल पोस्ट ऑब्जेक्ट्स का उपयोग कर रहे हैं।
1) लिपटे संग्रह की एक विशिष्ट प्रकार (उदाहरण के लिए, List
सार्वजनिक वर्ग WrappedListCollection बनाएं): WrappedCollectionBase, IList { निजी सूची innerList;
public WrappedListCollection(Action<T> addItemFunction, Func<T, bool> removeItemFunction, Action clearFunction)
: base(addItemFunction, removeItemFunction, clearFunction)
{
this.innerList = new List<T>();
}
protected override ICollection<T> GetWrappedCollection()
{
return this.innerList;
}
<...snip....> // fill in implementation of IList if important or don't implement IList
}
यह तो इस्तेमाल किया जा सकता:
public Customer Customer
{
public ICollection<Order> Orders {get { return _orders; } }
// Public methods.
public void AddOrder(Order order)
{
_orders.AddToInnerCollection(order);
}
// Private fields.
private WrappedListCollection<Order> _orders = new WrappedListCollection<Order>(this.AddOrder, null, null);
}
2) एक संग्रह दें का उपयोग कर लिपटे होने के लिए
public class WrappedCollection<T> : WrappedCollectionBase<T>
{
private ICollection<T> wrappedCollection;
public WrappedCollection(ICollection<T> collectionToWrap, Action<T> addItemFunction, Func<T, bool> removeItemFunction, Action clearFunction)
: base(addItemFunction, removeItemFunction, clearFunction)
{
this.wrappedCollection = collectionToWrap;
}
protected override ICollection<T> GetWrappedCollection()
{
return this.wrappedCollection;
}
}
जो इस प्रकार किया जा सकता है:
{ सार्वजनिक ICollection आदेश {प्राप्त {वापसी _wrappedOrders; }} // सार्वजनिक विधियां।
public void AddOrder(Order order)
{
_orders.Add(order);
}
// Private fields.
private ICollection<Order> _orders = new List<Order>();
private WrappedCollection<Order> _wrappedOrders = new WrappedCollection<Order>(_orders, this.AddOrder, null, null);
}
वहाँ WrappedCollection
कंस्ट्रक्टर्स उदाहरण के लिए, ओवरराइड करने के लिए कॉल करने के लिए जोड़ने लेकिन निकालने रखने के लिए और स्पष्ट रूप में सामान्य
private WrappedListCollection<Order> _orders = new WrappedListCollection(this.AddOrder, (Order o) => _orders.RemoveFromInnerCollection(o),() => _orders.ClearInnerCollection());
मैं मानता हूँ कि यह सबसे अच्छा हो सकता है अगर एफई की आवश्यकता नहीं होगी कुछ अन्य तरीके हैं संग्रह सार्वजनिक होना है लेकिन यह समाधान मुझे अपने संग्रह के संशोधन को नियंत्रित करने की अनुमति देता है।
क्वेरीिंग के लिए संग्रह तक पहुंच को रोकने की समस्या के लिए आप ऊपर 2 का उपयोग कर सकते हैं और NotSupportedException
फेंकने के लिए लपेटा गया चयन GetEnumerator
विधि सेट कर सकते हैं। फिर आपकी GetOrder
विधि इस तरह रह सकती है। लिपटे संग्रह को बेनकाब करने के लिए एक स्वच्छ विधि हो सकती है। उदाहरण के लिए:
public class WrappedCollection<T> : WrappedCollectionBase<T>
{
public ICollection<T> InnerCollection { get; private set; }
public WrappedCollection(ICollection<T> collectionToWrap, Action<T> addItemFunction, Func<T, bool> removeItemFunction, Action clearFunction)
: base(addItemFunction, removeItemFunction, clearFunction)
{
this.InnerCollection = collectionToWrap;
}
protected override ICollection<T> GetWrappedCollection()
{
return this.InnerCollection;
}
}
फिर GetOrder
विधि में कॉल यह पूरा करने के अपने Pocos से प्रत्येक के लिए एक संबद्ध इंटरफेस बनाने के लिए केवल बेनकाब करने के लिए क्या आप बाहर चाहते हो सकता है एक और तरीका है बन जाएगा
_orders.InnerCollection.Where(x => x.Id == id).Single();
अगर मैं कुछ भी लेकिन सार्वजनिक उस में मूल्यों को पढ़ने नहीं है करने के लिए अपने संग्रह की पहुँच संशोधक निर्धारित किया है। से "सुरक्षित" वापस करने के लिए "सार्वजनिक" एक साधारण स्विच, उदाहरण के लिए, यह सब काम करता है। साथ ही, यह सरल (उदा। स्ट्रिंग) गैर-सार्वजनिक गुणों को मानचित्रित नहीं कर रहा है। – dommer
एक और तरीका एक टी 4 फ़ाइल जोड़ने और संग्रह के लिए IENumerable की एपी प्रॉपर्टी का पर्दाफाश करने के लिए इसे संपादित करना और डिफ़ॉल्ट आईसीओलेक्शन गुण सुरक्षित करना है। –
Michael