c# - Composite from two base classses

I wantted to create a class, where it should be a singleton class, and it should also behave like a dictionary.

we have a Dictionary<TKey, TValue> class which has many operations that we want to have immediately, and we can aso create a Singleton base class, which may have the following definition. 

    /// <summary>
    /// Generic Single base classes
    /// </summary>
    public class ServiceSingletonBase<T> where T : class, new()
    {
        private static volatile T _instance = null;
        private static readonly object _lock = new object();

        public static T Instance 
        {
            get { 
                if (_instance == null)
                {
                    lock (_lock)
                    {
                        if (_instance == null)
                            _instance = new T();
                    }
                    return _instance;
                }
                else 
                    return _instance;
            }
        }

    }

To make a class singleton class, you can simply extend this base class and then make the contructor non-public. e.g.

class MyClass : ServiceSingletonBase<MyClass>
{
   protected|private|internal MyClass() { }
}

so what if I want to make a class which 1) is a singleton, 2) which behaves like a dictionary

you have two options, you can inherit your class from the SingletonBase class, and then you can implement IDictionary<TKey, Tvalue> and delegate all works to the inner dictionary object. an alternative option is to inherit from the Dictionary<TKey, TValue> class and then try to implement the pattern required by the singleton class. 

neither sound ideal... You cannnot reuse code fully (you have to either simulate the interface or you will need to write boilerplate/run-of-the-mill singleton pattern code). And you are bound by the single-inheritance-rule by C#.

however, with the help of wrapper by combining inheritance and composition, you might write someting like this 

class MyClassWrapper : Singleton<MyClassWrapper> {
{
   MyClass _myClass = new MyClass()
   public MyClass MyClass { get { return _myClass; } }
}

MyClass : Dictionary<string, TableId>
{
}

class TableId
{  public string Name {get; set;} public int InnerId { get; set; } 
}  

this way, you can call MyClassWrapper.Instance.MyClass and use  MyClassWrapper.Instance.MyClass in places where Dictionary is used....


however, what if you want to override some operation in Dictionary, such as maintain a Reverse Lookup dictoinary so that you can do query from "InnerId" to TableId? To achieve this, you will need to open the Add method call of Dictionary, and maintain the reverse table inside the Add method, this is definitely not something that you can get with just inherit Dictionary<TKey, TValue>

Now, we project our eyes back to the composition, but instead, we shall make MyClassWrapper implement IDictionary<Tkey, TValue>, so the code beomes: 

class MyClassWrapper : Singleton<MyClassWrapper>, IDictionary<string, TableId> {
{
   MyClass _myClass = new MyClass();
   // public MyClass MyClass { get { return _myClass; } }
   public Add(string key, TableId tableId) { _myClass.Add(string, tableId); }  }
   public Remove(string key) { _myClass.Remove(key); } 
   public this[string key] { get { return _myClass[key]; } set { _myClass[key] = value; } }
   //...

} MyClass : Dictionary<string, TableId> {} // omitted

this sound tedious, but at least you can inject some code such as 

class MyClassWrapper : Singleton<MyClassWrapper>, IDictionary<string, TableId> {
{
   // ... 
  Dictionary<int, TableId> _inverseTable; 
   public Add(string key, TableId tableId) { _myClass.Add(string, tableId); _inverseTable[talbeId] = tableId; }  }
   public Remove(string key) { _myClass.Remove(key); /* similar things here */ } 
   public this[string key] { get { return _myClass[key]; /* similar things here */ } set { _myClass[key] = value; /* additional things here*/ } }
   //...

}  MyClass : Dictionary<string, TableId> {} // omitted

the benefit is that you can use MyClassWrapper.Instance[key] = new TableId { ... }; but still we did not cut down the code we need to write. 


we ccan first try to cut back the code to wirte, by making a little sacrifice like this:

class MyClassWrapper : Singleton<MyClassWrapper> {
{
   // ... 
  private MyClass _myClass;
  public IDictionary<string, TableId> MyClass { get { return _myClas; }  }

}  class MyClass : Dictionary<string, TableId>, IDictionary<string, TableId> {  Dictionary<int, TableId> _inverseTable;
   IDictionary<string, TableId>.Add(string key, TableId tableId) { base.Add(string, tableId); _inverseTable[talbeId] = tableId; }  }
   IDictionary<string, TableId>.Remove(string key) { base.Remove(key); /* similar things here */ } 
   IDictionary<string, TableId>.this[string key] { get { return base[key]; /* similar things here */ } set { base[key] = value; /* additional things here*/ } }
   //...

 } // omitted

this is based on the assumption that we might only override part of the IDictionary interface. we inherit MyClass from Dictionary<string, TableId> so we can reuse most of the impl, and we implements IDictionary<string, tableId> so we cast it explicitly back to IDictionary<string, tableId>, we get the explicit implemented IDictionary<string, TableId>; and see that we have IDictionary<string, TableId> in the MyClassWrapper.

but still there is a bit cubersome in that you have to call. like MyClassWrapper.Instance.MyClass... still not good.

then, we know there is something called converter... 

however, there is limitation on the converter (we will implement the with implicit or explicit operator), so this is illegal in C#.

public static implicit operator IDictionary<string, TableId>(MyClassWrapper instance) { return instance._myclass; } 

hmmm. so another dead-end, we will think about Base class, which may have cloned interface as the base Dictionary, so we have the following design.

  public class MyClassWrapper : Singleton<MyClassWrapper>
  {
    private MyClass _myclass = new MyClass();
    public static implicit operator MyClassBase(MyClassWrapper instance) { return instance._myclass; }
  }

  public abstract class MyClassBase : Dictionary<string, TableId>
  {
    protected Dictionary<int, TableId> _inverseTable = new Dictionary<int,TableId>();

    public abstract void Add(string key, TableId value);
    public abstract bool Remove(string key);
    public abstract TableId this[string key] { get; set; }
  }


  public class MyClass : MyClassBase
  {
    public override void Add(string key, TableId value)
    {
      ((Dictionary<string, TableId>)this).Add(key, value);
      _inverseTable.Add(value.InnerId, value);
    }

    public override bool Remove(string key)
    {
      Dictionary<string, TableId> baseDict = ((Dictionary<string, TableId>)this);
      if (baseDict.ContainsKey(key))
      {
        var id = baseDict[key].InnerId;
        _inverseTable.Remove(id);
        return baseDict.Remove(key);
      }
      return false;
    }

    public override TableId this[string key]
    {
      get
      {
        Dictionary<string, TableId> baseDict = ((Dictionary<string, TableId>)this);
        return baseDict[key];
      }
      set
      {
        Dictionary<string, TableId> baseDict = ((Dictionary<string, TableId>)this);
        if (baseDict.ContainsKey(key))
        {
          var id = baseDict[key].InnerId;
          _inverseTable[id] = value;
        }
      }
    }
  }
now, what you cando with the new instance is like this: 
      ((MyClassBase)MyClassWrapper.Instance).Add("1", new TableId { InnerId = 1, Name = "1" }) ;
      Console.WriteLine("value = {0}", ((MyClassBase)MyClassWrapper.Instance)["1"].InnerId);
so, the cast is needed. but we have avoided the property acces. However, we have some potential risk, since user can tell the base class is a Dictionary<string, TableId>, and if such an conversion is attempted.
Dictionary<string, TableId> potentialRisk = ((Dictionary<string, TableId>)(MyClassBase) MyClassWrapper.Instance);

You will risk yourself of inconsisitence. 

Actually we shall create an interface which has a clone of parts of the Dictionary methods.  which can server better hide cast from being misused (actually we still cannot prevent it from casting, because the real object is known at runtime), we shall see this technique in next post - simulating/imitate interface. 

In the end of the post, actually there is a very interesting use of the Singleton base class that we have. so instead of Singleton<MyClassWrapper> we directl

public class MyClassWrapper : Singleton<MyClass>
  {
    //
  }
  // the Definition of MyClass, MyClassBase is the same as we have seen before. 
Though it saves us a log of trouble, it still have the trouble of exposing dangerous the internals to inadvent uses.
 

你可能感兴趣的:(C#)