c# - Imitate/Simulate Dictionary Interface to h...

As we have discussed that in the previous post - composite from two classes, we have examine the ways that to compose characteristic from two classes, well to a certain degree we have achieved the goal, but we left a hole where it may expose interface for compromise. 

the design rule to tell us we should separate interface from its implementaiton, and interface is the key to this design. 

however, we won't do IDictionary<string, TableId> as there are so interfaces that needs to be filled, and some are not necessary if we just want to maintain a inverse look up table. 

then it occurs to me how about if we can simulate only part of the interface (maybe borrow/clone part of the target inteface).

with this in mind, we can make a new interface as such.

    public interface ITableDictBase
    {
        void Add(string key, TableID tableId);
        TableID this[string key] {get; set;}
        void Remove(string key);
        Dictionary<string, TableID>.KeyCollection Keys { get; }
        Dictionary<string, TableID>.ValueCollection Values { get; }
        bool ContainsKey(string key);
    }
and we will make yet another interface with an additional member so we can have a inverse lookup ability . 
    internal interface ITableDict : ITableDictBase
    {
        string GetTableId(int innerId);
    }
so, we go ahead, with the separation. 

    public class TableIdDictWrapper : ServiceSingletonBase<TableIdDictWrapper>
    {
        // TODO:
        // reverse look up table from int -> TableId

        private InnerTableIdDict _tableIdDict = new InnerTableIdDict();
        public ITableDictBase TableIdDict
        {
            get { return _tableIdDict; }
        }

        internal ITableDict TableIdDictExtended
        {
            get { return _tableIdDict; }
        }
        
        // You can add something that helps you with 
        private class InnerTableIdDict : TableIdDict
        {
            internal InnerTableIdDict() { }
        }
    }
we have an private class which serves a way to hide. and we expose two properties, each is under a the sealed interface, one is public used to expose to the general public, and another is internal one, which we wish to exposed internally so we can have the concealed reverse lookup ability. 

Though it is not necessary, we have created an abstract base class to InnerTableIdDIct, and it has this:
    // you can even create a publich TableIdDict
    internal abstract class TableIdDict : Dictionary<string, TableID>, ITableDict {
        protected internal TableIdDict() { } // prevent it from being created outside

        protected Dictionary<int, TableID> _reverseDict = new Dictionary<int,TableID>();
    
        void  ITableDictBase.Add(string key, TableID tableId)
        {
            if (key == null) throw new ArgumentNullException("key");

            base.Add(key, tableId);
            _reverseDict.Add(tableId.InnerTableId, tableId);
        }

        TableID  ITableDictBase.this[string key]
        {
            get 
	        { 
		        return base[key];
	        }
	        set 
	        {
                if (base.ContainsKey(key)) // update 
                {
                    var innerId = base[key].InnerTableId;
                    base[key] = value;
                    _reverseDict[innerId] = value;
                }
                else // Add
                {
                    ((ITableDictBase)this).Add(key, value);
                }
	        }
        }

        void  ITableDictBase.Remove(string key)
        {
            if (key == null) throw new ArgumentNullException("key");

            if (base.ContainsKey(key))
            {
                var tableId = base[key];
 	            base.Remove(key);
                _reverseDict.Remove(tableId.InnerTableId);
            }
        }

        string ITableDict.GetTableId(int innerId)
        {
            if (_reverseDict.ContainsKey(innerId))
            {
                return _reverseDict[innerId].Name;
            }
            else
                throw new ArgumentException("Invalid InnerId provided!");
        }
    }
As we have seen, the TableIdDict serves the main implementation of the ITabledDict interface. and the default impl from Dictionary<string, TableId>lays the meat and potatoes of the impl.

and surely we can improve this by setting the type parameter to real wrapper class instead of the wrapper... 

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