Sunday, March 20, 2011

ICombinable .NET Interface

I'm finding myself in need of "combining" several instances of the same type. This type has several IList properties on it. I want to take each instance and combine the values of those IList properties across the instances, so my code only needs one of those instances.

I'm thinking of creating an ICombinable interface, but I'm wonder if there's something already out there that's suited to this?

   public interface ICombinable<T>
    {
        void CombineWith(T instance);
    }
From stackoverflow
  • Sounds like you need Concat

    var configs = dbConfig.configList.Concat(fileConfig.configList);
    
    JeffN825 : But I have several of these configLists on fileConfig and dbConfig that need concatanating...and then I want them all accessible through a single instance of MyConfigurationInfo
    arootbeer : There is definitely not enough information here for a comparison to an existing solution, but it sounds like you are trying to oversimplify your configuration. I'd recommend that you take a step back and analyze your design. Why do you have multiple sources of configuration info? If there is a valid reason, then you should be able to build a provider based on that logic that can expose your configuration coherently. But from your description I'm having a hard time working backwards to the design.
    JeffN825 : I have two different configuration sources of the same structure. One is for installation specific configuration information (this is stored in an xml config file). The second is application wide configuration settings that are pulled from a DB over WCF. Does that help?
  • I ended up using SelectMany and Select for this. IConfiguration is an interface for the MyConfigurationInfo class. GetMyConfigurationSources returns all the different IConfigurations (from files, DB, etc).

        // accumulates an enumerable property on IConfiguration
        public static IEnumerable<TValue> GetConfigurationValues<TValue>(Func<IConfiguration, IEnumerable<TValue>> selector)
        {
            // cast included for clarification only
            return (GetMyConfigurationSources() as IEnumerable<IConfiguration>)
                .Where(c => selector(c) != null)
                .SelectMany(selector);
        }
    
        // accumulates a non enumerable property on IConfiguration
        public static IEnumerable<TValue> GetConfigurationValues<TValue>(Func<IConfiguration, TValue> selector)
        {
            // cast included for clarification only
            return (GetMyConfigurationSources() as IEnumerable<IConfiguration>)
                .Where(c => selector(c) != null)
                .Select(selector);
        }
    
        // Example usage:
        static void Main()
        {
            string[] allEnumerableValues = GetConfigurationValues(c => c.SomeEnumerableConfigPropertyOfStrings);
            string[] allNonEnumerableValues = GetConfigurationValues(c => c.SomeNonEnumerableConfigPropertyString);
        }
    
  • Have you tried looking at System.Collections.Generic.HashSet<T>? If you add the same thing multiple times, only 1 item exists.

    JeffN825 : The question wasn't so much about how to distinct the values, but rather how to aggregate them and access them in a fluent way. Though +1, as incorporate a unique-ing HashSet into the Select/SelectMany solution below is a good idea!

0 comments:

Post a Comment