c# - Subclassing all classes in a 'chain' of subclasses -


i came example clarify question

we start base class

/// <summary> /// silly example class /// </summary> class cfilestream {     protected readonly string filepath;      public cfilestream(string filepath)     {         filepath = filepath;     }      public virtual void write(string s)     {         var stream = getstream(filepath);         //etc     }      /// <summary>     /// take filepath argument make subclassing easier     /// </summary>     protected virtual filestream getstream(string filepath)     {         return new filestream(filepath, filemode.openorcreate);     } } 

create subclass it

/// <summary> /// building on top of cfilestream, created encrypted version /// </summary> class cfilestreamencrypted : cfilestream {     private readonly string _key;      public cfilestreamencrypted(string filepath, string key):base(filepath)     {         _key = key;     }      /// <summary>     /// added complexity, let's wrap possible excepton     /// </summary>     public override void write(string s)     {         try         {             base.write(s);         }         catch (imaginarycryptoexception ex)         {             throw new imaginarycustomexception("bladibla", ex);         }     }      /// <summary>     /// wrap base stream in imaginary crypto class     /// </summary>     protected override filestream getstream(string filepath)     {         return new cimaginarycryptostream(base.getstream(filepath), _key);     } } 

now wish create second subclass, 1 works initial filewriter encrypted version.

the first 1 makes sense

/// <summary> /// building on top of cfilestream, created auto-split version /// </summary> class cfilestreamsplit : cfilestream {     public cfilestreamsplit(string filepath)          : base(filepath)     {     }      protected int counter;      /// <summary>     /// close stream , move next file @ appropriate time(s)     /// </summary>     public override void write(string s)     {                 {             stream stream;             if (imaginarybooleanmustsplit)                 stream = getstream(filepath);             //etc         } while (imaginarybooleandatalefttowrite);     }      /// <summary>     /// base stream altered filepath     /// </summary>     protected override filestream getstream(string filepath)     {         return base.getstream(getnextpath(filepath));     }      /// <summary>     /// ignore proper extension / file-exists etc.     /// </summary>     protected virtual string getnextpath(string filepath)     {         return filepath + ++counter;     } } 

the second 1 (below this) duplicate code, except constructor requires encryption key.

/// <summary> /// build same auto-split version time on top of encrypted subclass /// </summary> class cfilestreamsplitencrypted : cfilestreamencrypted {     public cfilestreamsplitencrypted(string filepath, string key)         : base(filepath, key)     {     }      /*      * note there no changes below line      */      protected int counter;      /// <summary>     /// close stream , move next file @ appropriate time(s)     /// </summary>     public override void write(string s)     {                 {             stream stream;             if (imaginarybooleanmustsplit)                 stream = getstream(filepath);             //etc         } while (imaginarybooleandatalefttowrite);     }      /// <summary>     /// base stream altered filepath     /// </summary>     protected override filestream getstream(string filepath)     {         return base.getstream(getnextpath(filepath));     }      /// <summary>     /// ignore proper extension / file-exists etc.     /// </summary>     protected virtual string getnextpath(string filepath)     {         return filepath + ++counter;     } } 

there of course lot of ways reduce amount of duplicate code here, have yet find 'the best' way, if there such thing. so; least time-consuming, cleanest, flexible way round issue in opinion/experience?

for different modifications decent way go may composition on inheritance. set classes responsible single thing, taking in base stream on constructions.

interface icfilestream {     void write(string s);     filestream getstream(string filepath); }  /// <summary> /// silly example class /// </summary> class cfilestream: icfilestream {     protected readonly string filepath;      public cfilestream(string filepath)     {         filepath = filepath;     }      public void write(string s)     {         var stream = getstream(filepath);         //etc     }      /// <summary>     /// take filepath argument make subclassing easier     /// </summary>     protected filestream getstream(string filepath)     {         return new filestream(filepath, filemode.openorcreate);     } }  /// <summary> /// building on top of cfilestream, created encrypted version /// </summary> class cfilestreamencrypted : icfilestream {     private readonly string _key;     private readonly icfilestream _stream;      public cfilestreamencrypted(string key, icfilestream stream)     {         _key = key;         _stream = stream;     }      /// <summary>     /// added complexity, let's wrap possible excepton     /// </summary>     public void write(string s)     {         try         {             _stream.write(s);         }         catch (imaginarycryptoexception ex)         {             throw new imaginarycustomexception("bladibla", ex);         }     }      /// <summary>     /// wrap base stream in imaginary crypto class     /// </summary>     protected filestream getstream(string filepath)     {         return new cimaginarycryptostream(_stream.getstream(filepath), _key);     } }  class cfilestreamsplit : icfilestream {     private readonly icfilestream _stream;      public cfilestreamsplit(icfilestream stream)      {         _stream = stream;     }      protected int counter;      /// <summary>     /// close stream , move next file @ appropriate time(s)     /// </summary>     public void write(string s)     {                 {             stream stream;             if (imaginarybooleanmustsplit)                 stream = getstream(filepath);             //etc         } while (imaginarybooleandatalefttowrite);     }      /// <summary>     /// base stream altered filepath     /// </summary>     protected filestream getstream(string filepath)     {         return _stream.getstream(getnextpath(filepath));     }      /// <summary>     /// ignore proper extension / file-exists etc.     /// </summary>     protected string getnextpath(string filepath)     {         return filepath + ++counter;     } } 

so when want splitting-crypto-filestream:

new  cfilestreamsplit(new cfilestreamencrypted("crypto-awesome-key", new cfilestream("c:\\blah..."))); 

this more flexible when want add loggingcfilestream example don't need add separate class each combination.


Comments

Popular posts from this blog

php - get table cell data from and place a copy in another table -

javascript - Mootools wait with Fx.Morph start -

php - Navigate throught databse rows -