I have a set of classes, each of which can open different types of files using an external application and tell that application to print the file to a particular printer. The classes all inherit a common abstract class and an interface.
internal interface IApplicationPrinter : IDisposable
{
string ApplicationExe { get; }
string ApplicationName { get; }
string[] PrintableExtensions { get; }
IApplicationPrinter CreateInstance(string Filename, string Printer);
void Print();
bool ExitApplicationAfterPrint { get; set; }
bool WaitApplicationExitOnPrint { get; set; }
System.IO.FileInfo PdfFile { get; protected set; }
}
internal abstract class ApplicationPrinter : IApplicationPrinter
{
...
}
internal class WordPrinter : ApplicationPrinter
{
internal static string[] PrintableExtensions { get { return new string[]{".doc", ".docx" }; } }
...
}
internal class ExcelPrinter : ApplicationPrinter
{
internal static string[] PrintableExtensions { get { return new string[]{".xls", ".xlsx" }; } }
...
}
I am trying to create a Dictionary
of printable file extensions and corresponding Type
s of classes that can print such files. I do not want to instantiate the classes in the dictionary.
private static Dictionary<string, Type> FileConverters;
static Printer()
{
FileConverters = new Dictionary<string, Type>();
foreach (string ext in WordPrinter.PrintableExtensions)
{
FileConverters.Add(ext, typeof(WordPrinter));
}
string filename = "textfile.txt";
string extension = filename.Substring(filename.LastIndexOf("."));
if (FileConverters.ContainsKey(extension))
{
IApplicationPrinter printer = ((IApplicationPrinter)FileConverters[extension]).CreateInstance(filename, "Printer");
printer.Print();
}
}
Is there any way to make Dictionary<string, Type> FileConverters
more type-safe, by restricting it to values that implement IApplicationPrinter? In other words, is something like this possible:
private static Dictionary<string, T> FileConverters where T: IApplicationPrinter;
Update: I do not want to store instances for the following two reasons:
string[] PrintableExtensions
). The dictionary stores extensions as keys. There is no utility in creating and storing multiple separates instance of the same class.I would do it slightly differently:
private Dictionary<String, Func<IApplicationPrinter>> _converters;
public void Initialise()
{
foreach (string ext in WordPrinter.PrintableExtensions)
{
_converters.Add(ext, () => new WordPrinter());
}
}
public IApplicationPrinter GetPrinterFor(String extension)
{
if (_converters.ContainsKey(extension)) //case sensitive!
{
return _converters[extension].Invoke();
}
throw new PrinterNotFoundException(extension);
}
This method will not store instances in the dictionary as you require, and will create you a new instance each time you call GetPrinterFor
. It also is more strongly typed as the return type of the Func<>
has to be an IApplicationPrinter
.
Not directly - remember that the things you're putting in your dictionary are Type
objects, not objects that implement IApplicationPrinter
.
Probably the best option here is to check that each type you add to your dictionary implements IApplicationPrinter
, by checking whether type.GetInterface("IApplicationPrinter")
returns null or not.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With