Reputation: 18117
How to return PdfDocument
outside of the method to read properties of the object? I understand that the method will throw the object is disposed
exception because using
will do the disposal job before it is returned.
I am asking for refactoring ideas. Maybe Actions fits here? Please provide with code ideas.
public PdfDocument Info(string inFile, string password)
{
try
{
using (var pdf = new PdfDocument(inFile, new PdfStandardDecryptionHandler(password)))
{
return pdf;
}
}
catch (IncorrectPasswordException)
{
throw new ApiException(ResponseMessageType.FilePasswordProtected);
}
catch (UnexpectedStructureException)
{
throw new ApiException(ResponseMessageType.FileDamaged);
}
}
Upvotes: 1
Views: 578
Reputation: 1175
How about turning the other way, not returning the object but injecting the Action?
public void ProcessPdf(string inFile, string password, Action<PdfDocument> action)
{
try
{
using (var pdf = new PdfDocument(inFile, new PdfStandardDecryptionHandler(password)))
{
action (pdf);
}
}
catch (IncorrectPasswordException)
{
throw new ApiException(ResponseMessageType.FilePasswordProtected);
}
catch (UnexpectedStructureException)
{
throw new ApiException(ResponseMessageType.FileDamaged);
}
}
call it like:
ProcessPdf(iniPath, "*****", (o) => DoSomething(o))
private void DoSomething (pdfDocument doc)
{
//....
}
pseudocode, not tested!
Upvotes: 0
Reputation: 1
First, if you want to return a disposable object, then the caller function should handle the disposing; So, no need for the using statement inside the object creation function.
When you want call the Info function to create a PdfDocument object, use try to call "Info(string,string)" and then dispose it (if it's not null) in the finally block.
public PdfDocument Info(string inFile, string password)
{
try
{
PdfDocument pdf = new PdfDocument(inFile, new PdfStandardDecryptionHandler(password));
return pdf;
}
catch (IncorrectPasswordException)
{
throw new ApiException(ResponseMessageType.FilePasswordProtected);
}
catch (UnexpectedStructureException)
{
throw new ApiException(ResponseMessageType.FileDamaged);
}
}
/////////////
AnotherFunction()
{
PdfDocument pdf = null;
try
{
pdf = Info("inFile", "password");
// Use the object
}
finally
{
pdf?.Dispose();
}
}
Upvotes: 0
Reputation: 174505
The using
statement is really syntactic sugar for a try{}finally{}
construct and is lowered by the compiler as follows:
// this ...
using(var thing = new DisposableThing())
{
...
}
// gets rewritten to:
var thing = new DisposableThing();
try
{
...
}
finally
{
if(thing is IDisposable)
{
((IDisposable)thing).Dispose();
}
}
So remove the using
statement from your method to prevent premature disposal:
public PdfDocument Info(string inFile, string password)
{
try
{
return new PdfDocument(inFile, new PdfStandardDecryptionHandler(password));
}
catch (IncorrectPasswordException)
{
throw new ApiException(ResponseMessageType.FilePasswordProtected);
}
catch (UnexpectedStructureException)
{
throw new ApiException(ResponseMessageType.FileDamaged);
}
}
At which point the consumer becomes responsible for disposing of it:
using (var pdf = Info(inFile, password))
{
// read properties from `pdf` here
}
Upvotes: 5