Étant donné que je ne peux pas changer la classe WriTeFile, existe-t-il un moyen de «chaîner» les méthodes d'instance pour ne pas avoir à référencer myObject plusieurs fois? Je recherche quelque chose comme myObject.Read().Open(param1);

Je peux écrire myObject.Open(param1).Read(); qui compile cependant Read () n'est pas exécuté.

// myObject.Open(param1).Read(); s'exécute mais il est exécuté comme méthode StreamReader et non comme méthode ReadTheFile. Aide VS négligée ...

class TestT211
{
    static void Main(string[] args)
    {
        var myObject = new ReadTheFile();

        myObject.Read(myObject.Open(@"C:\file.txt"));          
    } 
}

public class ReadTheFile
{
    private int _lineCounter = 0;
    private string _lineOfText;

    public StreamReader Open(string path)
    {
        return new StreamReader(path);
    }

    public void Read(StreamReader sr)
    {
        while ((_lineOfText = sr.ReadLine()) != null) {
            Console.WriteLine(_lineOfText);
        }
    }
}
0
Bendom 27 janv. 2019 à 13:15

3 réponses

Meilleure réponse

En utilisant un constructeur simple (c'est exagéré) mais vous pouvez réaliser ce que vous voulez:

 class TestT211
{
    static void Main(string[] args)
    {
        FileReaderBuilder.New.Open(@"C:\file.txt").Read();
    }
}

public class ReadTheFile
{
    private int _lineCounter = 0;
    private string _lineOfText;

    public StreamReader Open(string path)
    {
        return new StreamReader(path);
    }

    public void Read(StreamReader sr)
    {
        while ((_lineOfText = sr.ReadLine()) != null)
        {
            Console.WriteLine(_lineOfText);
        }
    }
}

public class FileReaderBuilder
{
    private readonly ReadTheFile _file;

    private StreamReader _streamReader;

    private FileReaderBuilder()
    {
        _file = new ReadTheFile();
    }

    public FileReaderBuilder Open(string path)
    {
         _streamReader = _file.Open(path);

        return this;
    }

    public FileReaderBuilder Read()
    {
        if (_streamReader == null)
        {
            throw new ArgumentNullException(nameof(_streamReader));
        }

        _file.Read(_streamReader);

        return this;
    }

    public static FileReaderBuilder New => new FileReaderBuilder();
}
0
LukaszBalazy 27 janv. 2019 à 10:32

Si vous voulez avoir une syntaxe comme une API Fluent, vous devez changer un point de votre classe. Vous devez d'abord demander à Open de renvoyer l'instance actuelle, puis utiliser cette instance pour appeler Read. Mais cela suppose que vous conservez le StreamReader en tant que variable interne de la classe

public class ReadTheFile : IDisposable
{
    private int _lineCounter = 0;
    private string _lineOfText;
    private StreamReader _sr = null;

    public ReadTheFile Open(string path)
    {
        _sr = new StreamReader(path);
        return this;
    }

    public void Read()
    {
        if(_sr == null) return;

        while ((_lineOfText = _sr.ReadLine()) != null) {
            Console.WriteLine(_lineOfText);
        }
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
    protected virtual void Dispose(bool disposing)
    {
        if (disposing) 
        {
            if(_sr != null) 
            {
               _sr.Close();
               _sr = null;
            }
        }
    }   
}

Et maintenant vous pouvez écrire

 using(ReadTheFile myObject = new ReadTheFile())
      myObject.Open(@"C:\file.txt").Read();

Notez que le fait d'avoir un StreamReader entre vos variables internes vous oblige à implémenter l'interface IDisposable pour fermer et supprimer correctement le Stream

1
Steve 27 janv. 2019 à 10:35

Si vous souhaitez ajouter plus de fonctionnalités à la classe sans y avoir accès, vous pouvez utiliser des extensions. Par exemple, pour utiliser ReadTheFile pour lire StreamReader.

public static class StreamReaderExtension
{
    public static StreamReader ReadEx(this StreamReader sr)
    {
        var readTheFile = new ReadTheFile();
        readTheFile.Read(sr);
        return sr;
    }
}

Et que l'appeler avec

myObject.Open(@"C:\file.txt").ReadEx();

Vous pouvez ajouter d'autres méthodes, mais ne pouvez pas remplacer celles de l'instance, vous devez donc créer un nouveau nom ou une nouvelle signature.

1
Ondřej Kubíček 27 janv. 2019 à 10:56