Stai facendo parecchio in una singola classe, detto questo vediamo cosa possiamo fare.
Prima di tutto, modifica il codice in modo da poter supportare meglio OCP . Lo faremo introducendo un dizionario che conterrà i processori e un'interfaccia correlata IFileTypeProcessor .
interface IFileTypeProcessor
{
// not sure what string you intended to return
string Process(FileStream fileStream);
}
class FileProcessor : IFileProcessor
{
private readonly IDictionary<string, IFileTypeProcessor> processors;
public FileProcessor(IDictionary<string, IFileTypeProcessor> processors)
{
this.processors = processors
}
public string Process(string fileName)
{
using (FileStream fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read))
{
BinaryReader binaryReader = new BinaryReader(fileStream);
string hexString = BinaryFunctions.BytesToHexString(binaryReader.ReadBytes(2));
string result = "";
if(!this.processors.ContainsKey(hexString))
{
throw new YourApplicationSpecificException();
}
return this.processors[hexString].Process(fileStream);
}
}
}
Quindi introduciamo una nuova classe chiamata FirstTwoByteHexKeyProvider che implementa una nuova interfaccia IKeyREader che diventerà quindi una dipendenza aggiuntiva dal CTOR. Includeremo anche alcune clausole di salvaguardia per aiutare i nostri utenti perché ci piacciono.
interface IKeyReader
{
string GetKeyAsHexString(FileStream filestream)
}
class FirstTwoByteHexKeyProvider : IKeyReader
{
public string GetKeyAsHexString(FileStream fileStream)
{
if(fileStream)
{
throw new ArgumentNullException(nameof(fileStream));
}
BinaryReader binaryReader = new BinaryReader(fileStream);
return BinaryFunctions.BytesToHexString(binaryReader.ReadBytes(2));
}
}
class FileProcessor : IFileProcessor
{
private readonly IDictionary<string, IFileTypeProcessor> processors;
private readonly IKeyReader keyReader;
public FileProcessor(IDictionary<string, IFileTypeProcessor> processors, IKeyReader keyReader)
{
if(processors == null)
{
throw new ArgumentNullException(nameof(fileStream));
}
if(keyReader == null)
{
throw new ArgumentNullException(nameof(keyReader));
}
this.processors = processors
this.keyReader = keyReader
}
public string Process(string fileName)
{
using (FileStream fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read))
{
string hexString = this.keyReader.GetKeyAsHexString(fileStream);
if(!this.processors.ContainsKey(hexString))
{
throw new YourApplicationSpecificException();
}
return this.processors[hexString].Process(fileStream);
}
}
}
Ora alle dipendenze, devi supportare solo Ninject? se così fosse potrebbe essere semplice come usare NinjectModules:
public class FileProcessorNinjectModule : NinjectModule
{
public override void Load()
{
Bind<IFileProcessor>().To<FileProcessor>();
Bind<IKeyReader>().To<FirstTwoByteHexKeyProvider>();
Bind<IDictionary<string, IFileTypeProcessor>>().ToMethod(context => new Dictionary<string,IFileTypeProcessor>
{
["123"] = new FileType1Processor(),
["456"] = new FileType2Processor(),
});
}
}
Una volta creato il modulo, consenti ai tuoi clienti di utilizzare qualche forma di Caricamento del modulo dinamico e Bob è tuo zio.
L'ho scritto velocemente qui e non l'ho testato tramite il compilatore, ma sono sicuro che funzionerà con un po 'di correzione da parte tua, ma dovrebbe essere sufficiente per farti andare.
Se devi supportare più di un modulo di DI allora ti consiglio di esporre un'interfaccia che consenta al cliente di fornire il proprio contenitore DI e il tuo pacchetto lo userà per risolvere le dipendenze allo stesso modo in cui ASP.NET Core lo fa oggi.
Infine potresti considerare di estrarre l'azione di leggere effettivamente il file in un'altra classe e di rendere il risultato binario di questo "file letto" un argomento che viene passato al tuo metodo di processo anziché al fileName dato che così com'è essere un po 'un dolore da testare.
Se non vuoi farlo, puoi perlomeno estrarre il "nuovo FileStream (..." in una funzione virtuale interna che ti darà la possibilità di MOQ attorno a questa chiamata di sistema durante il test dell'unità.
Spero che aiuti ...