Sunday, September 6, 2015

Enjoying Breeze after Refactoring

Recently I have done some refactoring in one of my c# projects. To show the process, I will give example of a class which was a huge *** 1880 line code with a long train of 22 else-if blocks. After refactoring it became 517 line code and much more manageable. Reflection, delegation, generics and lambda are used in this refactoring. By the way, I've omitted considerable amount of code from the example for readability, so these examples are not in workable state. I will not discuss these examples in detail.....he he.... just going to throw some code to you.

Here is the class before refactoring:

 namespace WebIMCP.GeoToolBox.XMLDOs  
 {  
   public class DefaultLayerBuilder  
   {  
     private DefaultLayerBuilder()  
     {  
     }  
     public static DefaultLayerBuilder Instance(string name, string filePrefix, Type layerType)  
     {  
       DefaultLayerBuilder instance = new DefaultLayerBuilder();  
       instance.name = name;  
       instance.filePrefix = filePrefix;  
       instance.layerType = layerType;  
       instance.addScaleRangeThemesToThemeDefination = true;  
       instance.addSelectionThemeToThemeDefination = true;  
       instance.populateThemeDefination = true;  
       instance.enableThematicScheme = false;  
       return instance;  
     }  
     public DefaultLayerBuilder Enable(bool val)  
     {  
       this.enabled = val;  
       return this;  
     }  
     public DefaultLayerBuilder Description(string val)  
     {  
       this.desc = val;  
       return this;  
     }  
     public ConfigurationLayer Build()  
     {  
       ConfigurationLayer cl = new ConfigurationLayer();  
       defaultScaleRangesData = getDefaultScaleRangesData();  
       defaultPointThemeData = getDefaultPointThemeData();  
       defaultPolylineThemeData = getDefaultPolylineThemeData();  
       defaultPolygonThemeData = getDefaultPolygonThemeData();  
       defaultPolylineLayerRoutingData = getDefaultPolylineLayerRoutingData();  
       defaultPolylineDirectionInfoData = getDefaultPolylineDirectionInfoData();  
       
       if (layerType == typeof(ConfigurationLayerPolygonLayer))  
       {  
         cl.PolygonLayer = new ConfigurationLayerPolygonLayer();  
         this.loadBasicInfoInTypedLayer(cl.PolygonLayer);  
         if (this.enableThematicScheme)  
         {  
           cl.PolygonLayer.ThematicScheme = new List<ConfigurationLayerPolygonLayerThematicScheme>();  
           cl.PolygonLayer.ThematicScheme.Add(new ConfigurationLayerPolygonLayerThematicScheme());  
           cl.PolygonLayer.ThematicScheme[0].Name = "PolygonLayer_DEFAULT_THEMATICSCHEME";  
           cl.PolygonLayer.ThematicScheme[0].ThematicScaleRanges =  
             defaultScaleRangesData  
             .Replace("<ThematicScaleRanges>", "<" + typeof(ConfigurationLayerPolygonLayerThematicSchemeThematicScaleRanges).Name + ">")  
             .Replace("</ThematicScaleRanges>", "</" + typeof(ConfigurationLayerPolygonLayerThematicSchemeThematicScaleRanges).Name + ">")  
             .XMLDeSerialize<ConfigurationLayerPolygonLayerThematicSchemeThematicScaleRanges>();  
           cl.PolygonLayer.ThematicScheme[0].SchemeSelectionTheme = cl.PolygonLayer.ThematicScheme[0].Name + "_SelectionTheme";  
         }  
         else  
         {  
           cl.PolygonLayer.Scheme = new List<ConfigurationLayerPolygonLayerScheme>();  
           cl.PolygonLayer.Scheme.Add(new ConfigurationLayerPolygonLayerScheme());  
           cl.PolygonLayer.Scheme[0].Name = "PolygonLayer_DEFAULT_SCHEME";  
           cl.PolygonLayer.Scheme[0].ScaleRanges =  
             defaultScaleRangesData  
             .Replace("<ScaleRanges>", "<" + typeof(ConfigurationLayerPolygonLayerSchemeScaleRanges).Name + ">")  
             .Replace("</ScaleRanges>", "</" + typeof(ConfigurationLayerPolygonLayerSchemeScaleRanges).Name + ">")  
             .XMLDeSerialize<ConfigurationLayerPolygonLayerSchemeScaleRanges>();  
           cl.PolygonLayer.Scheme[0].SchemeSelectionTheme =  
                         cl.PolygonLayer.Scheme[0].Name + "_SelectionTheme";  
         }  
         if (this.populateThemeDefination)  
         {  
           cl.PolygonLayer.ThemeDefinition = new List<ConfigurationLayerPolygonLayerPolygonTheme>();  
           if (this.addScaleRangeThemesToThemeDefination)  
           {  
             ConfigurationLayerPolygonLayerPolygonTheme defaultRangeTheme =  
               defaultPolygonThemeData  
               .Replace("<Theme", "<" + typeof(ConfigurationLayerPolygonLayerPolygonTheme).Name + "")  
               .Replace("</Theme>", "</" + typeof(ConfigurationLayerPolygonLayerPolygonTheme).Name + ">")  
               .Replace("<DisplayProperties", "<" + layerType.Name.Replace("Configuration", "").Replace("Layer", "") + "Properties")  
               .XMLDeSerialize<ConfigurationLayerPolygonLayerPolygonTheme>();  
             defaultRangeTheme.Name = cl.PolygonLayer.Scheme[0].ScaleRanges.DefaultRange.DefaultType.Theme;  
             cl.PolygonLayer.ThemeDefinition.Add(defaultRangeTheme);  
             foreach (ConfigurationLayerPolygonLayerSchemeScaleRangesScaleRange scaleRange  
                     in cl.PolygonLayer.Scheme[0].ScaleRanges.ScaleRange)  
             {  
               ConfigurationLayerPolygonLayerPolygonTheme scaleRangeTheme =  
               defaultPolygonThemeData  
               .Replace("<Theme", "<" + typeof(ConfigurationLayerPolygonLayerPolygonTheme).Name + "")  
               .Replace("</Theme>", "</" + typeof(ConfigurationLayerPolygonLayerPolygonTheme).Name + ">")  
               .Replace("<DisplayProperties", "<" + layerType.Name.Replace("Configuration", "").Replace("Layer", "") + "Properties")  
               .XMLDeSerialize<ConfigurationLayerPolygonLayerPolygonTheme>();  
               scaleRangeTheme.Name = scaleRange.DefaultType.Theme;  
               cl.PolygonLayer.ThemeDefinition.Add(scaleRangeTheme);  
             }  
           }  
           if (this.addSelectionThemeToThemeDefination)  
           {  
             ConfigurationLayerPolygonLayerPolygonTheme selectionTheme =  
               defaultPolygonThemeData  
               .Replace("<Theme", "<" + typeof(ConfigurationLayerPolygonLayerPolygonTheme).Name + "")  
               .Replace("</Theme>", "</" + typeof(ConfigurationLayerPolygonLayerPolygonTheme).Name + ">")  
               .Replace("<DisplayProperties", "<" + layerType.Name.Replace("Configuration", "").Replace("Layer", "") + "Properties")  
               .XMLDeSerialize<ConfigurationLayerPolygonLayerPolygonTheme>();  
             if (this.enableThematicScheme)  
             {  
               selectionTheme.Name = cl.PolygonLayer.ThematicScheme[0].SchemeSelectionTheme;  
             }  
             else  
             {  
               selectionTheme.Name = cl.PolygonLayer.Scheme[0].SchemeSelectionTheme;  
             }  
             cl.PolygonLayer.ThemeDefinition.Add(selectionTheme);  
           }  
         }  
       }  
       else if (layerType == typeof(ConfigurationLayerPolylineLayer))  
       {  
         cl.PolylineLayer = new ConfigurationLayerPolylineLayer();  
         this.loadBasicInfoInTypedLayer(cl.PolylineLayer);  
         cl.PolylineLayer.Scheme = new List<ConfigurationLayerPolylineLayerScheme>();  
         cl.PolylineLayer.Scheme.Add(new ConfigurationLayerPolylineLayerScheme());  
         cl.PolylineLayer.Scheme[0].Name = "PolylineLayer_DEFAULT_SCHEME";  
         cl.PolylineLayer.Scheme[0].ScaleRanges =  
           defaultScaleRangesData  
           .Replace("<ScaleRanges>", "<" + typeof(ConfigurationLayerPolylineLayerSchemeScaleRanges).Name + ">")  
           .Replace("</ScaleRanges>", "</" + typeof(ConfigurationLayerPolylineLayerSchemeScaleRanges).Name + ">")  
           .XMLDeSerialize<ConfigurationLayerPolylineLayerSchemeScaleRanges>();  
         cl.PolylineLayer.Scheme[0].SchemeSelectionTheme =  
                       cl.PolylineLayer.Scheme[0].Name + "_SelectionTheme";  
         if (this.populateThemeDefination)  
         {  
           cl.PolylineLayer.ThemeDefinition = new List<ConfigurationLayerPolylineLayerPolylineTheme>();  
           if (this.addScaleRangeThemesToThemeDefination)  
           {  
             ConfigurationLayerPolylineLayerPolylineTheme defaultRangeTheme =  
               defaultPolylineThemeData  
               .Replace("<Theme", "<" + typeof(ConfigurationLayerPolylineLayerPolylineTheme).Name + "")  
               .Replace("</Theme>", "</" + typeof(ConfigurationLayerPolylineLayerPolylineTheme).Name + ">")  
               .Replace("<DisplayProperties", "<" + layerType.Name.Replace("Configuration", "").Replace("Layer", "") + "Properties")  
               .XMLDeSerialize<ConfigurationLayerPolylineLayerPolylineTheme>();  
             defaultRangeTheme.Name = cl.PolylineLayer.Scheme[0].ScaleRanges.DefaultRange.DefaultType.Theme;  
             cl.PolylineLayer.ThemeDefinition.Add(defaultRangeTheme);  
             foreach (ConfigurationLayerPolylineLayerSchemeScaleRangesScaleRange scaleRange  
                     in cl.PolylineLayer.Scheme[0].ScaleRanges.ScaleRange)  
             {  
               ConfigurationLayerPolylineLayerPolylineTheme scaleRangeTheme =  
               defaultPolylineThemeData  
               .Replace("<Theme", "<" + typeof(ConfigurationLayerPolylineLayerPolylineTheme).Name + "")  
               .Replace("</Theme>", "</" + typeof(ConfigurationLayerPolylineLayerPolylineTheme).Name + ">")  
               .Replace("<DisplayProperties", "<" + layerType.Name.Replace("Configuration", "").Replace("Layer", "") + "Properties")  
               .XMLDeSerialize<ConfigurationLayerPolylineLayerPolylineTheme>();  
               scaleRangeTheme.Name = scaleRange.DefaultType.Theme;  
               cl.PolylineLayer.ThemeDefinition.Add(scaleRangeTheme);  
             }  
           }  
           if (this.addSelectionThemeToThemeDefination)  
           {  
             ConfigurationLayerPolylineLayerPolylineTheme selectionTheme =  
               defaultPolylineThemeData  
               .Replace("<Theme", "<" + typeof(ConfigurationLayerPolylineLayerPolylineTheme).Name + "")  
               .Replace("</Theme>", "</" + typeof(ConfigurationLayerPolylineLayerPolylineTheme).Name + ">")  
               .Replace("<DisplayProperties", "<" + layerType.Name.Replace("Configuration", "").Replace("Layer", "") + "Properties")  
               .XMLDeSerialize<ConfigurationLayerPolylineLayerPolylineTheme>();  
             selectionTheme.Name = cl.PolylineLayer.Scheme[0].SchemeSelectionTheme;  
             cl.PolylineLayer.ThemeDefinition.Add(selectionTheme);  
           }  
           cl.PolylineLayer.DirectionInfo = defaultPolylineDirectionInfoData  
               .XMLDeSerialize<ConfigurationLayerPolylineLayerDirectionInfo>();  
           cl.PolylineLayer.Routing = defaultPolylineLayerRoutingData  
               .XMLDeSerialize<ConfigurationLayerPolylineLayerRouting>();  
         }  
       }  
       else if (layerType == typeof(ConfigurationLayerPointLayer))  
       {  
         cl.PointLayer = new ConfigurationLayerPointLayer();  
         this.loadBasicInfoInTypedLayer(cl.PointLayer);  
         if (this.enableThematicScheme)  
         {  
           cl.PointLayer.ThematicScheme = new List<ConfigurationLayerPointLayerThematicScheme>();  
           cl.PointLayer.ThematicScheme.Add(new ConfigurationLayerPointLayerThematicScheme());  
           cl.PointLayer.ThematicScheme[0].Name = "PointLayer_DEFAULT_THEMATICSCHEME";  
           cl.PointLayer.ThematicScheme[0].ThematicScaleRanges =  
             defaultScaleRangesData  
             .Replace("<ThematicScaleRanges>", "<" + typeof(ConfigurationLayerPointLayerThematicSchemeThematicScaleRanges).Name + ">")  
             .Replace("</ThematicScaleRanges>", "</" + typeof(ConfigurationLayerPointLayerThematicSchemeThematicScaleRanges).Name + ">")  
             .XMLDeSerialize<ConfigurationLayerPointLayerThematicSchemeThematicScaleRanges>();  
           cl.PointLayer.ThematicScheme[0].SchemeSelectionTheme = cl.PointLayer.ThematicScheme[0].Name + "_SelectionTheme";  
         }  
         else  
         {  
           cl.PointLayer.Scheme = new List<ConfigurationLayerPointLayerScheme>();  
           cl.PointLayer.Scheme.Add(new ConfigurationLayerPointLayerScheme());  
           cl.PointLayer.Scheme[0].Name = "PointLayer_DEFAULT_SCHEME";  
           cl.PointLayer.Scheme[0].ScaleRanges =  
             defaultScaleRangesData  
             .Replace("<ScaleRanges>", "<" + typeof(ConfigurationLayerPointLayerSchemeScaleRanges).Name + ">")  
             .Replace("</ScaleRanges>", "</" + typeof(ConfigurationLayerPointLayerSchemeScaleRanges).Name + ">")  
             .XMLDeSerialize<ConfigurationLayerPointLayerSchemeScaleRanges>();  
           cl.PointLayer.Scheme[0].SchemeSelectionTheme =  
                         cl.PointLayer.Scheme[0].Name + "_SelectionTheme";  
         }  
         if (this.populateThemeDefination)  
         {  
           cl.PointLayer.ThemeDefinition = new List<ConfigurationLayerPointLayerPointTheme>();  
           if (this.addScaleRangeThemesToThemeDefination)  
           {  
             ConfigurationLayerPointLayerPointTheme defaultRangeTheme =  
               defaultPointThemeData  
               .Replace("<Theme", "<" + typeof(ConfigurationLayerPointLayerPointTheme).Name + "")  
               .Replace("</Theme>", "</" + typeof(ConfigurationLayerPointLayerPointTheme).Name + ">")  
               .Replace("<DisplayProperties", "<" + layerType.Name.Replace("Configuration", "").Replace("Layer", "") + "Properties")  
               .XMLDeSerialize<ConfigurationLayerPointLayerPointTheme>();  
             defaultRangeTheme.Name = cl.PointLayer.Scheme[0].ScaleRanges.DefaultRange.DefaultType.Theme;  
             cl.PointLayer.ThemeDefinition.Add(defaultRangeTheme);  
             foreach (ConfigurationLayerPointLayerSchemeScaleRangesScaleRange scaleRange  
                     in cl.PointLayer.Scheme[0].ScaleRanges.ScaleRange)  
             {  
               ConfigurationLayerPointLayerPointTheme scaleRangeTheme =  
               defaultPointThemeData  
               .Replace("<Theme", "<" + typeof(ConfigurationLayerPointLayerPointTheme).Name + "")  
               .Replace("</Theme>", "</" + typeof(ConfigurationLayerPointLayerPointTheme).Name + ">")  
               .Replace("<DisplayProperties", "<" + layerType.Name.Replace("Configuration", "").Replace("Layer", "") + "Properties")  
               .XMLDeSerialize<ConfigurationLayerPointLayerPointTheme>();  
               scaleRangeTheme.Name = scaleRange.DefaultType.Theme;  
               cl.PointLayer.ThemeDefinition.Add(scaleRangeTheme);  
             }  
           }  
           if (this.addSelectionThemeToThemeDefination)  
           {  
             ConfigurationLayerPointLayerPointTheme selectionTheme =  
               defaultPointThemeData  
               .Replace("<Theme", "<" + typeof(ConfigurationLayerPointLayerPointTheme).Name + "")  
               .Replace("</Theme>", "</" + typeof(ConfigurationLayerPointLayerPointTheme).Name + ">")  
               .Replace("<DisplayProperties", "<" + layerType.Name.Replace("Configuration", "").Replace("Layer", "") + "Properties")  
               .XMLDeSerialize<ConfigurationLayerPointLayerPointTheme>();  
             if (this.enableThematicScheme)  
             {  
               selectionTheme.Name = cl.PointLayer.ThematicScheme[0].SchemeSelectionTheme;  
             }  
             else  
             {  
               selectionTheme.Name = cl.PointLayer.Scheme[0].SchemeSelectionTheme;  
             }  
             cl.PointLayer.ThemeDefinition.Add(selectionTheme);  
           }  
         }  
       }  
       return cl;  
     }    
   }  
 }  


And here is the same class after refactoring:


 namespace WebIMCP.GeoToolBox  
 {  
   class DefaultLayerBuilder  
   {  
     private DefaultLayerBuilder()  
     {  
     }  
     public static DefaultLayerBuilder Instance(string name, string filePrefix, Type layerType)  
     {  
       DefaultLayerBuilder instance = new DefaultLayerBuilder();  
       instance.name = name;  
       instance.filePrefix = filePrefix;  
       instance.layerType = layerType;  
       instance.addScaleRangeThemesToThemeDefination = true;  
       instance.addSelectionThemeToThemeDefination = true;  
       instance.populateThemeDefination = true;  
       instance.enableThematicScheme = false;  
       instance.load();  
       return instance;  
     }  
     public DefaultLayerBuilder Enable(bool val)  
     {  
       this.enabled = val;  
       return this;  
     }  
     public DefaultLayerBuilder Description(string val)  
     {  
       this.desc = val;  
       return this;  
     }  
     public ConfigurationLayer Build()  
     {  
       if (this.layerType == null)  
       {  
         throw new ArgumentNullException("layerType");  
       }   
       if(!this.LayerFunctionMap.ContainsKey(this.layerType))   
       {  
         throw new ArgumentException("layer type not found", "layerType");  
       }  
       ConfigurationLayer cl = new ConfigurationLayer();  
       string schemeName = this.layerType.Name.Replace("ConfigurationLayer", "")   
                 + (this.enableThematicScheme ? "_DEFAULT_THEMATICSCHEME" : "_DEFAULT_SCHEME");  
       dynamic typedLayer = this.LayerFunctionMap[this.layerType](schemeName);  
       PropertyInfo[] conLayerproInfoList = cl.GetType().GetProperties();  
       PropertyInfo conLayerproInfo = conLayerproInfoList.SingleOrDefault(i => i.PropertyType == this.layerType);  
       conLayerproInfo.SetValue(cl, typedLayer);  
       return cl;  
     }  
     private void load()  
     {  
       this.defaultScaleRangesData = getDefaultScaleRangesData();  
       this.defaultPointThemeData = getDefaultPointThemeData();  
       this.defaultPolylineThemeData = getDefaultPolylineThemeData();  
       this.defaultPolygonThemeData = getDefaultPolygonThemeData();  
       this.defaultPolylineLayerRoutingData = getDefaultPolylineLayerRoutingData();  
       this.defaultPolylineDirectionInfoData = getDefaultPolylineDirectionInfoData();  

       this.LayerFunctionMap = new Dictionary<Type, Func<string, dynamic>>();
       LayerFunctionMap.Add(typeof(ConfigurationLayerPolygonLayer),  
       schemeName => this.getTypedLayer<ConfigurationLayerPolygonLayer, ConfigurationLayerPolygonLayerScheme, ConfigurationLayerPolygonLayerSchemeScaleRanges,  
                   ConfigurationLayerPolygonLayerThematicScheme, ConfigurationLayerPolygonLayerThematicSchemeThematicScaleRanges,  
                   ConfigurationLayerPolygonLayerPolygonTheme>(schemeName, this.defaultPolygonThemeData));  
       LayerFunctionMap.Add(typeof(ConfigurationLayerPolylineLayer),  
       schemeName => this.getTypedLayer<ConfigurationLayerPolylineLayer, ConfigurationLayerPolylineLayerScheme, ConfigurationLayerPolylineLayerSchemeScaleRanges,  
                   ConfigurationLayerPolylineLayerPolylineTheme, ConfigurationLayerPolylineLayerDirectionInfo, ConfigurationLayerPolylineLayerRouting>  
                   (schemeName, this.defaultPolylineThemeData, this.defaultPolylineDirectionInfoData, this.defaultPolylineLayerRoutingData));  
       LayerFunctionMap.Add(typeof(ConfigurationLayerPointLayer),  
       schemeName => this.getTypedLayer<ConfigurationLayerPointLayer, ConfigurationLayerPointLayerScheme, ConfigurationLayerPointLayerSchemeScaleRanges,   
                   ConfigurationLayerPointLayerThematicScheme, ConfigurationLayerPointLayerThematicSchemeThematicScaleRanges,   
                   ConfigurationLayerPointLayerPointTheme>(schemeName, this.defaultPointThemeData));  
     }  
     private dynamic getTypedLayer<L, S, R, T, D, RT>(string schemeName, string defaultThemeData,  
                 string defaultDirectionInfoData, string defaultRoutingData)  
       where L : new()  
       where S : new()  
       where R : new()  
       where T : new()  
       where D : new()  
       where RT : new()  
     {  
       dynamic Layer = new L();  
       this.loadBasicInfoInTypedLayer(Layer);  
       Layer.Scheme = new List<S>();  
       Layer.Scheme.Add(new S());  
       Layer.Scheme[0].Name = schemeName;  
       Layer.Scheme[0].ScaleRanges =  
         defaultScaleRangesData  
         .Replace("<ScaleRanges>", "<" + typeof(R).Name + ">")  
         .Replace("</ScaleRanges>", "</" + typeof(R).Name + ">")  
         .XMLDeSerialize<R>();  
       Layer.Scheme[0].SchemeSelectionTheme = Layer.Scheme[0].Name + "_SelectionTheme";  
       if (this.populateThemeDefination)  
       {  
         Layer.ThemeDefinition = new List<T>();  
         if (this.addScaleRangeThemesToThemeDefination)  
         {  
           dynamic defaultRangeTheme =  
             defaultThemeData  
             .Replace("<Theme", "<" + typeof(T).Name + "")  
             .Replace("</Theme>", "</" + typeof(T).Name + ">")  
             .Replace("<DisplayProperties", "<" + typeof(L).Name.Replace("Configuration", "").Replace("Layer", "") + "Properties")  
             .XMLDeSerialize<T>();  
           defaultRangeTheme.Name = Layer.Scheme[0].ScaleRanges.DefaultRange.DefaultType.Theme;  
           Layer.ThemeDefinition.Add(defaultRangeTheme);  
           foreach (dynamic scaleRange in Layer.Scheme[0].ScaleRanges.ScaleRange)  
           {  
             dynamic scaleRangeTheme =  
             defaultThemeData  
             .Replace("<Theme", "<" + typeof(T).Name + "")  
             .Replace("</Theme>", "</" + typeof(T).Name + ">")  
             .Replace("<DisplayProperties", "<" + typeof(L).Name.Replace("Configuration", "").Replace("Layer", "") + "Properties")  
             .XMLDeSerialize<T>();  
             scaleRangeTheme.Name = scaleRange.DefaultType.Theme;  
             Layer.ThemeDefinition.Add(scaleRangeTheme);  
           }  
         }  
         if (this.addSelectionThemeToThemeDefination)  
         {  
           dynamic selectionTheme =  
           defaultThemeData  
           .Replace("<Theme", "<" + typeof(T).Name + "")  
           .Replace("</Theme>", "</" + typeof(T).Name + ">")  
           .Replace("<DisplayProperties", "<" + typeof(L).Name.Replace("Configuration", "").Replace("Layer", "") + "Properties")  
           .XMLDeSerialize<T>();  
           selectionTheme.Name = Layer.Scheme[0].SchemeSelectionTheme;  
           Layer.ThemeDefinition.Add(selectionTheme);  
         }  
         Layer.DirectionInfo = defaultDirectionInfoData.XMLDeSerialize<D>();  
         Layer.Routing = defaultRoutingData.XMLDeSerialize<RT>();  
       }  
       return Layer;  
     }  
     private dynamic getTypedLayer<L, S, R, TS, TR, T>(string schemeName, string defaultThemeData)  
       where L : new()  
       where S : new()  
       where R : new()  
       where TS : new()  
       where TR : new()  
       where T : new()  
     {  
       dynamic Layer = new L();  
       this.loadBasicInfoInTypedLayer(Layer);  
       if (this.enableThematicScheme)  
       {  
         Layer.ThematicScheme = new List<TS>();  
         Layer.ThematicScheme.Add(new TS());  
         Layer.ThematicScheme[0].Name = schemeName;  
         Layer.ThematicScheme[0].ThematicScaleRanges =  
           defaultScaleRangesData  
           .Replace("<ThematicScaleRanges>", "<" + typeof(TR).Name + ">")  
           .Replace("</ThematicScaleRanges>", "</" + typeof(TR).Name + ">")  
           .XMLDeSerialize<TR>();  
         Layer.ThematicScheme[0].SchemeSelectionTheme = Layer.ThematicScheme[0].Name + "_SelectionTheme";  
       }  
       else  
       {  
         Layer.Scheme = new List<S>();  
         Layer.Scheme.Add(new S());  
         Layer.Scheme[0].Name = schemeName;  
         Layer.Scheme[0].ScaleRanges =  
           defaultScaleRangesData  
           .Replace("<ScaleRanges>", "<" + typeof(R).Name + ">")  
           .Replace("</ScaleRanges>", "</" + typeof(R).Name + ">")  
           .XMLDeSerialize<R>();  
         Layer.Scheme[0].SchemeSelectionTheme = Layer.Scheme[0].Name + "_SelectionTheme";  
       }  
       if (this.populateThemeDefination)  
       {  
         Layer.ThemeDefinition = new List<T>();  
         if (this.addScaleRangeThemesToThemeDefination)  
         {  
           dynamic defaultRangeTheme =  
             defaultThemeData  
             .Replace("<Theme", "<" + typeof(T).Name + "")  
             .Replace("</Theme>", "</" + typeof(T).Name + ">")  
             .Replace("<DisplayProperties", "<" + typeof(L).Name.Replace("Configuration", "").Replace("Layer", "") + "Properties")  
             .XMLDeSerialize<T>();  
           defaultRangeTheme.Name = Layer.Scheme[0].ScaleRanges.DefaultRange.DefaultType.Theme;  
           Layer.ThemeDefinition.Add(defaultRangeTheme);  
           foreach (dynamic scaleRange in Layer.Scheme[0].ScaleRanges.ScaleRange)  
           {  
             dynamic scaleRangeTheme =  
             defaultThemeData  
             .Replace("<Theme", "<" + typeof(T).Name + "")  
             .Replace("</Theme>", "</" + typeof(T).Name + ">")  
             .Replace("<DisplayProperties", "<" + typeof(L).Name.Replace("Configuration", "").Replace("Layer", "") + "Properties")  
             .XMLDeSerialize<T>();  
             scaleRangeTheme.Name = scaleRange.DefaultType.Theme;  
             Layer.ThemeDefinition.Add(scaleRangeTheme);  
           }  
         }  
         if (this.addSelectionThemeToThemeDefination)  
         {  
           dynamic selectionTheme =  
             defaultThemeData  
             .Replace("<Theme", "<" + typeof(T).Name + "")  
             .Replace("</Theme>", "</" + typeof(T).Name + ">")  
             .Replace("<DisplayProperties", "<" + layerType.Name.Replace("Configuration", "").Replace("Layer", "") + "Properties")  
             .XMLDeSerialize<T>();  
           if (this.enableThematicScheme)  
           {  
             selectionTheme.Name = Layer.ThematicScheme[0].SchemeSelectionTheme;  
           }  
           else  
           {  
             selectionTheme.Name = Layer.Scheme[0].SchemeSelectionTheme;  
           }  
           Layer.ThemeDefinition.Add(selectionTheme);  
         }  
       }  
       return Layer;  
     }  
   }  
 }