@@ -8,11 +8,16 @@ namespace Microsoft.Windows.PowerShell.ScriptAnalyzer.Generic
88 // This is still an experimental class. Use at your own risk!
99 public abstract class ConfigurableScriptRule : IScriptRule
1010 {
11- // Configurable rules should define a default value
11+ // Configurable rule properties should define a default value
1212 // because if reading the configuration fails
1313 // we use the property's default value
14- [ ConfigurableRuleProperty ( ) ]
15- public bool Enable { get ; protected set ; } = false ;
14+ [ ConfigurableRuleProperty ( defaultValue : false ) ]
15+ public bool Enable { get ; protected set ; }
16+
17+ protected ConfigurableScriptRule ( )
18+ {
19+ SetDefaultValues ( ) ;
20+ }
1621
1722 public virtual void ConfigureRule ( IDictionary < string , object > paramValueMap )
1823 {
@@ -23,29 +28,37 @@ public virtual void ConfigureRule(IDictionary<string, object> paramValueMap)
2328
2429 try
2530 {
26- var properties = GetConfigurableProperties ( ) ;
27- foreach ( var property in properties )
31+ foreach ( var property in GetConfigurableProperties ( ) )
2832 {
2933 if ( paramValueMap . ContainsKey ( property . Name ) )
3034 {
31- var type = property . PropertyType ;
32- var obj = paramValueMap [ property . Name ] ;
33-
34- // TODO Check if type is convertible
35- property . SetValue (
36- this ,
37- System . Convert . ChangeType ( obj , type ) ) ;
35+ SetValue ( property , paramValueMap [ property . Name ] ) ;
3836 }
3937 }
4038 }
4139 catch
4240 {
4341 // we do not know how to handle an exception in this case yet!
44- // but we know that this should not crash the program hence we
45- // have this empty catch block
42+ // but we know that this should not crash the program
43+ // hence we revert the property values to their default
44+ SetDefaultValues ( ) ;
45+ }
46+ }
47+
48+ private void SetDefaultValues ( )
49+ {
50+ foreach ( var property in GetConfigurableProperties ( ) )
51+ {
52+ SetValue ( property , GetDefaultValue ( property ) ) ;
4653 }
4754 }
4855
56+ private void SetValue ( PropertyInfo property , object value )
57+ {
58+ // TODO Check if type is convertible
59+ property . SetValue ( this , Convert . ChangeType ( value , property . PropertyType ) ) ;
60+ }
61+
4962 private IEnumerable < PropertyInfo > GetConfigurableProperties ( )
5063 {
5164 foreach ( var property in this . GetType ( ) . GetProperties ( ) )
@@ -57,6 +70,19 @@ private IEnumerable<PropertyInfo> GetConfigurableProperties()
5770 }
5871 }
5972
73+ private Object GetDefaultValue ( PropertyInfo property )
74+ {
75+ var attr = property . GetCustomAttribute ( typeof ( ConfigurableRulePropertyAttribute ) ) ;
76+ if ( attr == null )
77+ {
78+ throw new ArgumentException (
79+ String . Format ( Strings . ConfigurableScriptRulePropertyHasNotAttribute , property . Name ) ,
80+ nameof ( property ) ) ;
81+ }
82+
83+ return ( ( ConfigurableRulePropertyAttribute ) attr ) . DefaultValue ;
84+ }
85+
6086 public abstract IEnumerable < DiagnosticRecord > AnalyzeScript ( Ast ast , string fileName ) ;
6187 public abstract string GetCommonName ( ) ;
6288 public abstract string GetDescription ( ) ;
@@ -69,6 +95,16 @@ private IEnumerable<PropertyInfo> GetConfigurableProperties()
6995 [ AttributeUsage ( AttributeTargets . Property , AllowMultiple = false ) ]
7096 public class ConfigurableRulePropertyAttribute : Attribute
7197 {
98+ public object DefaultValue { get ; private set ; }
7299
100+ public ConfigurableRulePropertyAttribute ( object defaultValue )
101+ {
102+ if ( defaultValue == null )
103+ {
104+ throw new ArgumentNullException ( nameof ( defaultValue ) , Strings . ConfigurableScriptRuleNRE ) ;
105+ }
106+
107+ DefaultValue = defaultValue ;
108+ }
73109 }
74110}
0 commit comments