Консольный вывод перенаправления к текстовому полю в отдельной программе

Просто потому, что я думаю, что другие ответы в значительной степени касаются касательной того, является ли футбольная команда «is-a» List<FootballPlayer> или «has-a» List<FootballPlayer>, которая на самом деле не отвечает на этот вопрос, как написано .

ОП в основном просит уточнить принципы наследования с List<T>:

. В руководстве говорится, что вы не должны наследовать List<T>. Почему нет?

Поскольку List<T> не имеет виртуальных методов. Это меньше проблем в вашем собственном коде, поскольку вы обычно можете отключить реализацию с относительно небольшой болью, но может быть гораздо более крупной сделкой в ​​публичном API.

Что такое публикация API и почему мне это нужно?

Открытый API - это интерфейс, который вы предоставляете сторонним программистам. Подумайте о каркасе. И помните, что ссылки, на которые ссылаются, - это «Рекомендации по дизайну .NET Framework », а не «Рекомендации по дизайну .NET ». Существует разница, и, вообще говоря, публичный дизайн API гораздо более строгий.

Если мой текущий проект не имеет и вряд ли когда-либо будет иметь этот открытый API, могу ли я безопасно игнорировать это руководство? Если я наследую List, и мне кажется, что мне нужен публичный API, какие трудности у меня есть?

В значительной степени, да. Возможно, вам стоит подумать об обоснованности этого вопроса, чтобы убедиться, что оно применимо к вашей ситуации в любом случае, но если вы не создаете публичный API, вам не нужно беспокоиться об особенностях API, таких как управление версиями (из которых это подмножество).

Если вы добавите публичный API в будущем, вам нужно будет либо абстрагировать свой API от вашей реализации (не подвергая непосредственно ваше List<T>), либо нарушать рекомендации с возможным будущим боль, которая влечет за собой.

Почему это даже имеет значение? Список - это список. Что может измениться? Что я могу изменить?

Зависит от контекста, но поскольку мы используем FootballTeam в качестве примера - представьте, что вы не можете добавить FootballPlayer, если он приведет к тому, что команда перейдет на зарплату. Возможный способ добавить это будет следующим:

 class FootballTeam : List<FootballPlayer> {
     override void Add(FootballPlayer player) {
        if (this.Sum(p => p.Salary) + player.Salary > SALARY_CAP)) {
          throw new InvalidOperationException("Would exceed salary cap!");
        }
     }
 }

А ... но вы не можете override Add, потому что это не virtual (по соображениям производительности).

Если вы находитесь в приложении (которое в основном означает, что вы и все ваши собеседники скомпилированы вместе), вы можете теперь изменить на IList<T> и исправить любые ошибки компиляции:

 class FootballTeam : IList<FootballPlayer> {
     private List<FootballPlayer> Players { get; set; }

     override void Add(FootballPlayer player) {
        if (this.Players.Sum(p => p.Salary) + player.Salary > SALARY_CAP)) {
          throw new InvalidOperationException("Would exceed salary cap!");
        }
     }
     /* boiler plate for rest of IList */
 }

, но если вы публично выступили с третьим лицом, вы только что внесли изменения, которые могут привести к ошибкам компиляции и / или времени выполнения.

TL; DR - руководящие принципы для общедоступных API. Для частных API выполните то, что вы хотите.

49
задан John Saunders 20 March 2014 в 05:06
поделиться

3 ответа

Это работает на меня:

void RunWithRedirect(string cmdPath)
{
    var proc = new Process();
    proc.StartInfo.FileName = cmdPath;

    // set up output redirection
    proc.StartInfo.RedirectStandardOutput = true;
    proc.StartInfo.RedirectStandardError = true;    
    proc.EnableRaisingEvents = true;
    proc.StartInfo.CreateNoWindow = true;
    // see below for output handler
    proc.ErrorDataReceived += proc_DataReceived;
    proc.OutputDataReceived += proc_DataReceived;

    proc.Start();

    proc.BeginErrorReadLine();
    proc.BeginOutputReadLine();

    proc.WaitForExit();
}

void proc_DataReceived(object sender, DataReceivedEventArgs e)
{
    // output will be in string e.Data
}
70
ответ дан Mark Maxham 7 November 2019 в 11:48
поделиться

Можно использовать следующий код

        MemoryStream mem = new MemoryStream(1000);
        StreamWriter writer = new StreamWriter(mem);
        Console.SetOut(writer);

        Assembly assembly = Assembly.LoadFrom(@"C:\ConsoleApp.exe");
        assembly.EntryPoint.Invoke(null, null);
        writer.Close();

        string s = Encoding.Default.GetString(mem.ToArray());
        mem.Close();
4
ответ дан Ahmed Said 7 November 2019 в 11:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: