standard newbie disclaimer: Sono nuovo di CIO e sono sempre segnali contrastanti. Sto cercando alcune indicazioni sulla seguente situazione per favore.Sono parametri del costruttore primitive una cattiva idea quando si utilizza un IoC Container?
Supponiamo che io ho la seguente interfaccia e l'implementazione:
public interface IImageFileGenerator
{
void RenameFiles();
void CopyFiles();
}
public class ImageFileGenerator : IImageFileGenerator
{
private readonly IList<IImageLink> _links;
private readonly string _sourceFolder;
private readonly string _destinationFolder;
private readonly int _folderPrefixLength;
public ImageFileGenerator(IList<IImageLink> links, string sourceFolder, string destinationFolder)
{
_links = links;
_sourceFolder = sourceFolder;
_destinationFolder = destinationFolder;
_folderPrefixLength = 4;
}
public void RenameFiles()
{
// Do stuff, uses all the class fields except destination folder
}
public void CopyFiles()
{
// Do stuff, also uses the class fields
}
}
sto ottenendo confuso se devo inviare solo di interfaccia/dipendenze al costruttore, creare qualche oggetto parametro e passarlo al costruttore o tenerlo così com'è e passa i parametri al momento della risoluzione di un'istanza.
Quindi c'è un modo più corretto di creare questo codice per funzionare al meglio con un contenitore IoC? Una delle seguenti cose sarebbe preferibile in termini di design rispetto al mio attuale layout?
1.
public interface IImageFileGenerator
{
void RenameFiles(IList<IImageLink> links, string sourceFolder);
void CopyFiles(IList<IImageLink> links, string sourceFolder, stringDestFolder);
}
public class ImageFileGenerator : IImageFileGenerator
{
private readonly int _folderPrefixLength;
public ImageFileGenerator()
{
_folderPrefixLength = 4;
}
public void RenameFiles(IList<IImageLink> links, string sourceFolder)
{
// Do stuff
}
public void CopyFiles(IList<IImageLink> links, string sourceFolder, stringDestFolder)
{
// Do stuff
}
}
Non mi piace che sto passando la stessa cosa in entrambi i casi (tranne la cartella di destinazione). Nella implementazione corrente del IImageFileGenerator, devo eseguire entrambi i metodi e sono stati necessari gli stessi valori per ciascun metodo. Ecco perché ho passato lo stato in via del costruttore.
2.
public interface IImageFileGenerator
{
void RenameFiles();
void CopyFiles();
}
public class ImageLinkContext
{
// various properties to hold the values needed in the
// ImageFileGenerator implementation.
}
public class ImageFileGenerator : IImageFileGenerator
{
private readonly IList<IImageLink> _links;
private readonly string _sourceFolder;
private readonly string _destinationFolder;
private readonly int _folderPrefixLength;
public ImageFileGenerator(ImageLinkContext imageLinkContext)
{
// could also use these values directly in the methods
// by adding a single ImageLinkContext field and skip
// creating the other fields
_links = imageLinkContext.ImageLinks;
_sourceFolder = imageLinkContext.Source;
_destinationFolder = imageLinkContext.Destination;
_folderPrefixLength = 4;
}
public void RenameFiles()
{
// Do stuff, uses all the class fields except destination folder
}
public void CopyFiles()
{
// Do stuff, uses all the class fields
}
}
Questo approccio può anche essere ottimizzato per un Servizio di facciata (precedentemente chiamato i servizi di aggregazione) come detto da Mark Seemann here.
Ho anche letto che è possibile utilizzare le proprietà per questi valori e utilizzare l'iniezione di proprietà, anche se sembra che non sia più preferito (le dichiarazioni di autofac è preferibile l'iniezione del costruttore ... Ninject credo che abbia rimosso anche l'abilità nella versione 2).
In alternativa ho letto che è anche possibile creare un metodo di inizializzazione e assicurarsi che le proprietà siano impostate lì.
così tante opzioni e sto diventando più confuso come ho letto di più su questa roba. Sono sicuro che non c'è modo corretto definitiva (o forse non v'è, almeno per questo esempio ???), ma forse qualcuno può fornire pro ei contro di ogni approccio. O forse c'è un altro approccio che mi è totalmente mancato.
Mi rendo conto ora che questa domanda è probabilmente un po 'sul lato soggettivo (ed è davvero più di una domanda), ma spero che tu possa perdonarmi e fornire una guida.
PS - Attualmente sto provando la mia mano con autofac nel caso in cui ciò influenzi il design che potrebbe adattarsi meglio.
NOTA: ho apportato una leggera modifica al codice relativo alla cartella di destinazione ... non è utilizzato da RenameFiles (potrebbe avere un impatto sulla risposta).
Ecco una discussione correlata sull'iniezione di * servizi * vs * dati *: http://stackoverflow.com/questions/1818539/how-to-pass-controllers-modelstate-to-my-service-constructor-with-autofac –
@Peter Lillevold: Interessante, passerò un po 'di tempo a guardare i delegati della fabbrica. Posso vederli tornare utile. Grazie per il link (e l'articolo allegato nella risposta: http://peterspattern.com/generate-generic-factories-with-autofac/). –