Проще говоря, вы берете ярлыки, которые вы просто не можете взять.Как буквально говорит заголовок вашего вопроса, вы пытаетесь использовать объект, который зависит от объекта, которым вы располагаете.
Что вы пытаетесь сделать, это открыть файл, прочитать некоторые информация о его внутренностях (не самих внутренних), , затем , закрытие файла, и , а затем попытка использовать эту информацию для фактического чтения из этого файла.Это невозможно; файл уже закрыт. Точно так же, как вы не можете вернуть одноразовый объект из его собственного блока using
, не заканчивая удаленным и, таким образом, непригодным объектом, вы, очевидно, также не можете вернуть то, что зависит от одноразового предмета.
Итак, в целом весь мыслительный процесс, стоящий за вашей getMyArchiveStream
функцией, несовершенен.Вы не должны иметь эту функцию вообще.Вам просто нужно настроить другую функцию следующим образом:
public void UseMyArchiveStream()
{
using(var archive = ZipFile.OpenRead(_filepath))
{
var entry = archive.GetEntry("test.path");
using(var myStream = entry.Open())
{
//Do stuff
}
}
}
Одна альтернатива - оставить archive
открытым ... но, как прокомментировал mjwills , есть другой способ сделатьчто вы хотите, и это, чтобы дать UseMyArchiveStream
Action<>
или Func<>
в качестве аргумента.Это буквально означает, что комментарий «Делать вещи» в приведенном выше коде заменяется вызовом любой функции, которую вы задаете в качестве аргумента:
public void UseMyArchiveStream(String zipPath, String entryName, Action<Stream, String> doStuff)
{
using (var archive = ZipFile.OpenRead(zipPath))
{
var entry = archive.GetEntry(entryName);
using (var myStream = entry.Open())
{
doStuff(myStream, entry.FullName);
}
}
}
Демонстрируется с функцией void SaveStreamToFile(Stream file, String filename)
:
UseMyArchiveStream(_filepath, "test.path", (str, nm) => SaveStreamToFile(str, nm));
С помощью Func<>
вы можете сделать перегрузку, которая также возвращает значение.Последний аргумент внутри <>
всегда является типом возвращаемого значения.Но вы можете легко использовать обобщения, чтобы они зависели от вызывающего ввода:
public T UseMyArchiveStream<T>(String zipPath, String entryName, Func<Stream, String, T> doStuff)
{
using (var archive = ZipFile.OpenRead(zipPath))
{
var entry = archive.GetEntry(entryName);
using (var myStream = entry.Open())
{
return doStuff(myStream, entry.FullName);
}
}
}
Вы можете вызывать это так же, только с функцией, которая возвращает значение, а не void
.Демонстрируется с помощью Boolean DostuffWithFile(Stream file, String entryName)
:
Boolean ok = UseMyArchiveStream(_filepath, "test.path", (str, nm) => DostuffWithFile(str, nm));
Обратите внимание, что вызываемая функция не обязательно должна соответствовать точной сигнатуре аргумента.Таким способом вызова можно полностью заменить отсутствующие аргументы локальными данными.
Демонстрируется с Boolean DostuffWithFile(Stream file, String entryName, Boolean someOption, String outputFolder)
:
Boolean ok = UseMyArchiveStream(_filepath, "test.path", (str, nm) => DostuffWithFile(str, nm, true, _savePath));
Это будет работать до тех пор, пока ввод, который должен быть предоставленUseMyArchiveStream
это просто часть перед =>
.Конечно, вы можете манипулировать аргументами так, как хотите;Вы можете даже дать функции весь объект ZipArchiveEntry
и, возможно, даже источник ZipFile
, так что вы можете делать с ним все, что захотите.
Единственный недостаток этого подхода заключается в том, что вы можете 'На самом деле имена компонентов Action<>
или Func<>
не имеют, поэтому в этом случае вы не можете узнать только из сигнатуры функции UseMyArchiveStream
, получит ли этот String
аргумент, заданный Func<Stream, String, T>
, entry.Name
или entry.FullName
.То же самое относится к предоставлению нескольких аргументов одного типа;если у вас есть пять логических опций в этом Func<>
, вам может быть трудно вспомнить точно, что именно, без необходимости каждый раз заглядывать в код.Поэтому не забудьте точно документировать это в комментариях к функциям, чтобы избежать путаницы позже.