I am struggling with the concept of always using composition, there are many articles that mention virtually all uses of inheritance can be replaced with composition. I understand there are benefits of it such as testing... but how can I replace the use of inheritance in this case?
Basically I have 2 decorators, that add functionality to an existing file service class. Before copying the files, I want it to rename them and then delegate back to the original file service.
In this example, I have two methods. One loops though a theoretical list of files and then calls Copy File. Instead of duplicating the code, the decorator class simply calls the wrapped implementations version instead, similar to utilizing inheritance.
However, this doesn't work like inheritance because now it's never going to call the decorators CopyFile method because it is now in the previous base class implementation, it is not aware that the decorators CopyFile method exists.
If I use inheritance, by marking the method as virtual the base class would know when one of its functions has been overrided and call that version instead of its own.
How can I mimic this functionality only using composition?
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApp5
{
public interface IFileService
{
void CopyFile(string source, string destination);
void CopyFiles(IEnumerable<string> source, string destination);
}
public class MainFileService : IFileService
{
public void CopyFile(string source, string destination)
{
Console.WriteLine("Base Method of Copy File invoked");
}
public void CopyFiles(IEnumerable<string> source, string destination)
{
foreach (var file in source)
{
CopyFile(file,destination);
}
}
}
public class RenamingFileService : IFileService
{
private IFileService _wrapper;
public RenamingFileService(IFileService wrapper)
{
this._wrapper = wrapper;
}
public void CopyFile(string source, string destination)
{
RenameFileExtensionToPART();
_wrapper.CopyFile(source, destination);
}
private void RenameFileExtensionToPART()
{
Console.WriteLine($"Now invoking {nameof(RenameFileExtensionToPART)}");
}
public void CopyFiles(IEnumerable<string> source, string destination)
{
_wrapper.CopyFiles(source, destination);
}
}
public class FileLoggingService : IFileService
{
private IFileService _wrapper;
public FileLoggingService(IFileService wrapper)
{
this._wrapper = wrapper;
}
public void CopyFile(string source, string destination)
{
Console.WriteLine("Logged Request");
_wrapper.CopyFile(source, destination);
}
public void CopyFiles(IEnumerable<string> source, string destination)
{
Console.WriteLine("Logging requests.");
_wrapper.CopyFiles(source, destination);
}
}
class Program
{
static void Main(string[] args)
{
var service = new FileLoggingService(new RenamingFileService(new MainFileService()));
service.CopyFiles(Enumerable.Range(0,10).Select(x => Guid.NewGuid().ToString()),"Directory");
}
}
}
Aucun commentaire:
Enregistrer un commentaire