0

First of all I do not know how to explain the question properly. Therefore i explain it in more detail, maybe there is a completly different solution which i do not think of.

I search for a solution for the following problem: We went from one ORM to another. Both use different generic classes when accessing collections.

One uses List or IList

public IList<ItemTypeA> AItems{
...
}

the other one a vendor specific collection

public ACollection<ItemTypeA> AItems{
...
}

For some time we will have them in parallel until everything is tested and switched to the later.

The first idea was to use defines

#if ORMS_OLD
public IList<ItemTypeA> AItems{
...
}
#endif
#if ORMS_A
public ACollection<ItemTypeA> AItems{
...
}
#endif

Now it is a bit errorprone as it is still worked on the code to just double the code for another ORM. The inside of the properties and methods would be over 90% the same.

Another idea was to declare a base list and only change it there:

public class BaseList<T> 
#if ORMS_OLD 
    : List<T>
#endif
#if ORMS_A
    : ACollection<T>
#endif
{
}

but this looks also a bit clumsy and there was a note that you should not inherit from List because of performance reasons.

What i want to do is more a sort of defining a replacement pattern and just use the replacement pattern:

#define PLACEHOLDERLIST #if ORMS_OLD IList #else ACollection
public #PLACEHOLDERLIST<ItemTypeA> AItems{

and let some kind of preprocessor or makro-intelligence run over it.

I dont know the right word to define what i want to do. I think a sort of inline replacement or inline code generation (not a T4 generation - this is a bit clumsy to be tested ).

Is there something or exist a pattern which would be better for this use case.

Offler
  • 1,223
  • 1
  • 12
  • 34

2 Answers2

0

you could

  1. make your ACollection<T> implement ICollection<T> (list already implements it)
  2. make your AItems unique (I mean, do not duplicate it with preprocessor instructions) and as ICollection<T>
  3. use the Activator.CreateInstance in order to create your concrete list type whenever you need it (here is an example: Purpose of Activator.CreateInstance with example? )
hub
  • 31
  • 2
  • As I understood the question, `ACollection` is a 3rd Party Type and cannot be changed. – Fildor Sep 11 '19 at 13:47
  • ACollection is a vendor collection. The collections/List are for example properties of persistent objects pushed by ORM from / to DB. Don't see how 3 could help in this case – Offler Sep 11 '19 at 14:27
0

Ok maybe I misunderstood the need but here is how I would process: Couldn't that solve your issue ? You would just need to adapt your properties to be of type TheNewCollectionToUse<T>

public class TheNewCollectionToUse<T> : ACollection<T>, ICollection<T>
        {
            public TheNewCollectionToUse()
            {
#if ORMS_OLD
                TheList = new List<T>();
#else
                TheList = new ACollection<T>();
#endif
            }

#if ORMS_OLD
            public TheNewCollectionToUse(List<T> theList)
            {
                TheList = theList;
            }

            public ICollection<T> TheList { get; set; }

            public int Count => TheList.Count();
            public bool IsReadOnly => TheList.IsReadOnly;

            public void Add(T item)
            {
                TheList.Add(item);
            }

            public void Clear()
            {
                TheList.Clear();
            }

            public bool Contains(T item)
            {
                return TheList.Contains(item);
            }

            public void CopyTo(T[] array, int arrayIndex)
            {
                TheList.CopyTo(array, arrayIndex);
            }

            public IEnumerator<T> GetEnumerator()
            {
                return TheList.GetEnumerator();
            }

            public bool Remove(T item)
            {
                return TheList.Remove(item);
            }

            IEnumerator IEnumerable.GetEnumerator()
            {
                return TheList.GetEnumerator();
            }

#else
            public TheNewCollectionToUse(ACollection<T> theList)
            {
                TheList = theList;
            }

            public ACollection<T> TheList { get; set; }

            public int Count; // put suitable code for ACollection

            public bool IsReadOnly; // put suitable code for ACollection

            public void Add(T item)
            {
                // put suitable code for ACollection
            }

            public void Clear()
            {
                // put suitable code for ACollection
            }

            public bool Contains(T item)
            {
                // put suitable code for ACollection
            }

            public void CopyTo(T[] array, int arrayIndex)
            {
                // put suitable code for ACollection
            }

            public IEnumerator<T> GetEnumerator()
            {
                // put suitable code for ACollection
            }

            public bool Remove(T item)
            {
                // put suitable code for ACollection
            }

            IEnumerator IEnumerable.GetEnumerator()
            {
                // put suitable code for ACollection
            }

            // --------------------------------------------------------------
            // add more methods if needed to override ACollection methods
            // --------------------------------------------------------------
#endif      
        }

I would also add overriden methods to ACollection<T> in the ACollection #if statement

hub
  • 31
  • 2