There’s a Service for That

A question came up yesterday with regards to how to create SalesLogix ids within the Web Framework. In the legacy client and our external development we would generally call a provider Stored procedure that would give us the Id. The code might look as the following

List<string> list = new List<string>();

using (
       var cmd = new OleDbCommand(string.Format("slx_dbids('{0}', {1})", table, count), 
       connection)
)
{

   var r = cmd.ExecuteReader();

   while (r.Read())
   {
      list.Add(r.GetString(0));
   }

    r.Close();
 }

return list;

Now within the SalesLogix web client infrastructure it is a actually easier if you know where to look.

The framework exposes a service – SalesLogixEntityKeyGenerator. You can get access to this service using the following code;

SalesLogixEntityKeyGenerator generator = 
ApplicationContext.Current.Services.Get<SalesLogixEntityKeyGenerator>(false);

 

Once you have access to the generator it its very easy to get a set of keys;

List<string> keys = new List<string>(generator.GenerateIds(typeof(IHistory), 1));

 

There you have it.

Visual Studio Quick Hint

I really like Visual Studio 2010. I have been using it for a couple of weeks and its growing on me nicely. I have been playing around with the Parallel extenstions and other .net 4.0 things but yesterday I found that there is a new ‘quick’ feature that I have wished for and just found out it was there. Get this you can now copy project references from one project to another one. Yup, nothing special but a time save none-the-less.

I’ve seen the ‘Dynamic’ Light

Hey did you hear, VS 2010 is released and production worthy. We at BITtelligent did not wait long to start to put it into our daily work flow and I have to say I am quite impressed and happy that we did. In in the IDE side, but more so in the C#4 language improvements.

We are working on a large project with a different complexity challenges. The project is loosely based on a current implementation that is in production. That being said there are instances of where system settings are retrieved from the database to determine the process flow.

so code exists such as

if (cbool(container.settings.LocateValueFromSetting(“aaaa aaaa aaaa”)) = true

Now for me the intent is lost in the complexity of the check. This means more comments and a harder time for someone to grok my code.

Its quite possible to wrap the settings type with either proxy or add extension methods to allow for a better maintainability.

code such as;

ProxyClass proxy = new ProxyClass(settings);
if (proxy.ShouldExecuteSomeCode())
{

}
- or - 
public static bool ShouldExecuteSomeCode(this SpecialDataSet settings)
{
   return Convert.ToBoolean(settings.FindSettingBySettingName("Should Execute Some Code"));
}

Now this code needs to be repeated for each and every setting value and that seems to me to be a pretty heavy handed way of coding up the solution.

Enter dynamic.

Since I was looking for the most efficient and manageable way to provide settings access I moved into using a dictionary<string, object> as my local storage mechanism.  and for explanation purposes the following code is included;

 public class DynamicSettingClass : DynamicObject 
    {
        Dictionary<string, object> _values;

        /// <summary>
        /// Initializes a new instance of the DynamicSettingClass class.
        /// </summary>
        /// <param name="values"></param>
        public DynamicSettingClass(Dictionary<string, object> values)
        {
            _values = values;
        }

        /// <summary>
        /// Initializes a new instance of the DynamicSettingClass class.
        /// </summary>
        public DynamicSettingClass()
        {
            _values = new Dictionary<string, object>(StringComparer.InvariantCultureIgnoreCase);    
        }

        public void AddSettingValue(string key, object value)
        {
            if (_values.ContainsKey(key))
                _values[key] = value;
            else
                _values.Add(key, value);

        }

        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            string keyName = FormattedName(binder.Name);
            if (_values.ContainsKey(keyName))
            {
                result = _values[keyName];
                return true;
            }

            return base.TryGetMember(binder, out result);
        }

        private static string FormattedName(string name)
        {
            if (name.IndexOf('_') > 0) name = name.Replace('_', ' ');
            return name;
        }

    }

What this class enables is the ability to address each of the setting values as a property of our object instead of as a collection item.

Now the secret sauce is in the TryGetMember, and Formatted name. Within the TryGetMember we are provided important information in the binder object but for our sample the most important is the name property. From it we can derrive the targeted setting we are looking for. I add a little preprocessing to the key value as settings values can contain spaces, so a little token replace is required. The final outcome is that I can use this utility class to enhance the readability of my code and reduce the amount of lines to write to get the experience for all of my setting requirements.

so to now access the setting using the following code I would do the following;

dynamic simpleSettings = new DynamicSettingClass();
simpleSettings.AddSetting("Should_Execute_Some_Code", true);

if (simpleSettings.Should_Execute_Some_Code)
{
}

This seems to be a simpler syntax for accessing my settings list but really having to call the AddSetting method seems incomplete. So we can finally and a little more ‘magic’ to our settings class;

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        string keyName = FormattedName(binder.Name);
        AddSettingValue(keyName, value);
        return true;
    }

With this little snippet the round tripping is now possible with our Dynamic property example;

simpleSettings.Should_Execute_Some_Code = true;

if (simpleSettings.Should_Execute_Some_Code)
{
}

So this completes this post. I hope it helps you out in seeing the power of the DynamicObject’s power.