Click here to Skip to main content
15,886,422 members
Articles / General Programming / Algorithms

Jazz Up Your C# Code

Rate me:
Please Sign up or sign in to vote.
4.95/5 (11 votes)
3 Jul 2012CPOL28 min read 51.5K   369   54  
Maintaining code with complex permissions tends to be difficult, because the code can be distributed across multiple classes. By embedding permissions directly on methods and properties within a class, code is reduced and maintainability is simplified.
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;

namespace Newtonsoft.Json.Linq
{
  internal class JPropertyKeyedCollection : Collection<JToken>
  {
    private static readonly IEqualityComparer<string> Comparer = StringComparer.Ordinal;

    private Dictionary<string, JToken> _dictionary;

    private void AddKey(string key, JToken item)
    {
      EnsureDictionary();
      _dictionary[key] = item;
    }

    protected void ChangeItemKey(JToken item, string newKey)
    {
      if (!ContainsItem(item))
        throw new ArgumentException("The specified item does not exist in this KeyedCollection.");

      string keyForItem = GetKeyForItem(item);
      if (!Comparer.Equals(keyForItem, newKey))
      {
        if (newKey != null)
          AddKey(newKey, item);

        if (keyForItem != null)
          RemoveKey(keyForItem);
      }
    }

    protected override void ClearItems()
    {
      base.ClearItems();

      if (_dictionary != null)
        _dictionary.Clear();
    }

    public bool Contains(string key)
    {
      if (key == null)
        throw new ArgumentNullException("key");

      if (_dictionary != null)
        return _dictionary.ContainsKey(key);

      return false;
    }

    private bool ContainsItem(JToken item)
    {
      if (_dictionary == null)
        return false;

      string key = GetKeyForItem(item);
      JToken value;
      return _dictionary.TryGetValue(key, out value);
    }

    private void EnsureDictionary()
    {
      if (_dictionary == null)
        _dictionary = new Dictionary<string, JToken>(Comparer);
    }

    private string GetKeyForItem(JToken item)
    {
      return ((JProperty)item).Name;
    }

    protected override void InsertItem(int index, JToken item)
    {
      AddKey(GetKeyForItem(item), item);
      base.InsertItem(index, item);
    }

    public bool Remove(string key)
    {
      if (key == null)
        throw new ArgumentNullException("key");

      if (_dictionary != null)
        return _dictionary.ContainsKey(key) && Remove(_dictionary[key]);

      return false;
    }

    protected override void RemoveItem(int index)
    {
      string keyForItem = GetKeyForItem(Items[index]);
      RemoveKey(keyForItem);
      base.RemoveItem(index);
    }

    private void RemoveKey(string key)
    {
      if (_dictionary != null)
        _dictionary.Remove(key);
    }

    protected override void SetItem(int index, JToken item)
    {
      string keyForItem = GetKeyForItem(item);
      string keyAtIndex = GetKeyForItem(Items[index]);

      if (Comparer.Equals(keyAtIndex, keyForItem))
      {
        if (_dictionary != null)
          _dictionary[keyForItem] = item;
      }
      else
      {
        AddKey(keyForItem, item);

        if (keyAtIndex != null)
          RemoveKey(keyAtIndex);
      }
      base.SetItem(index, item);
    }

    public JToken this[string key]
    {
      get
      {
        if (key == null)
          throw new ArgumentNullException("key");

        if (_dictionary != null)
          return _dictionary[key];

        throw new KeyNotFoundException();
      }
    }

    public bool TryGetValue(string key, out JToken value)
    {
      if (_dictionary == null)
      {
        value = null;
        return false;
      }

      return _dictionary.TryGetValue(key, out value);
    }

    public ICollection<string> Keys
    {
      get
      {
        EnsureDictionary();
        return _dictionary.Keys;
      }
    }

    public ICollection<JToken> Values
    {
      get
      {
        EnsureDictionary();
        return _dictionary.Values;
      }
    }

    public bool Compare(JPropertyKeyedCollection other)
    {
      if (this == other)
        return true;

      // dictionaries in JavaScript aren't ordered
      // ignore order when comparing properties
      Dictionary<string, JToken> d1 = _dictionary;
      Dictionary<string, JToken> d2 = other._dictionary;

      if (d1.Count != d2.Count)
        return false;

      foreach (KeyValuePair<string, JToken> keyAndProperty in d1)
      {
        JToken secondValue;
        if (!d2.TryGetValue(keyAndProperty.Key, out secondValue))
          return false;

        JProperty p1 = (JProperty)keyAndProperty.Value;
        JProperty p2 = (JProperty)secondValue;

        if (!p1.Value.DeepEquals(p2.Value))
          return false;
      }

      return true;
    }
  }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer TrackerRealm
Canada Canada
Charles Wiebe and John Hansen are Microsoft .NET software architect/designer, for Windows Forms and ASP.NET solutions.
Charles specializes in the application layer – Web Parts and other ways of building GUI’s. John specializes in high capacity object oriented systems and connectivity.

John and Charles are co-developers of Jetfire – a .net open source, multi-user, application domain specific language (DSL) with syntax heavily based on C# and Java. The goal of Jetfire is to allow power users to quickly and easily develop and deploy applications, in much the same way as Excel allows powers users to quickly develop spread sheets.

Their latest project is Jazz - a compact, modular framework that allows new, or existing, applications to easily employ roles, states, ACLs and void safety. Jazz allows complete workflows to be implemented in only a few hundred lines of C# or VB code.

Comments and Discussions