I have an interface for implementing an "output formatter" that looks a bit like this:
public interface IFormatOutput {}
public class HtmlOutputFormatter : IFormatOutput {}
public class TextOutputFormatter : IFormatOutput {}
// etc, etc...
public enum OutputFormat {
Html,
Text,
HappyMeal,
Excel
}
public class SomeFormattableEntity {
int Id { get; set; }
OutputFormat OutputType { get; set; }
}
So SomeFormattableEntity
is persisted in a database via Dapper and its OutputType
property is stored as the underlying integer value (ie, in an INT
column). As you can guess, I want to provide an instance of a IFormatOutput
to handle a SomeFormattableEntity
based on its OutputType
property.
Is there some clean best-practice way to handle this type of relationship? My ideas so far include a factory with innards potentially consisting of:
I realize it is not desirable to require an instance of a thing whose type is based on a value, but it seems hard to avoid this when SQL is involved. Basically the problem is that multiple "things" that all have varying .NET types are stored in a single table. I keep running into this idiom and am unable to find an elegant solution to it.
How about:
OutputFormat format = OutputFormat.Excel;
object obj = Activator.CreateInstance("myAssemblyName", format.ToString());
Assuming the elements of your enum has the exact name of your types?
I'd probably go for a custom attribute with a FormatsOutputFor property. Then decorate all of your implementations of IFormatOutput
with the attribute. eg
[YourAttribute(OutputFormat.Html)]
public class HtmlOutputFormatter : IFormatOutput {}
Then in your factory:
// get all your formatters
var formatters = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(p => Attribute.IsDefined(p, typeof(YourAttribute)));
// Now go through each formatter and use the attribute to figure out which
// output format it's for. Add these to some static IDictionary<OutputFormat, Type>
You probably want to build some internal cache that maps an OutputFormat
value to a Type
. Then your factory can double check that you have only got one type mapped to each output format and if you try to get a formatter for an enum value that doesn't have a corresponding class then you wont get some obscure TypeLoadException from activator.
Hopefully that makes sense...
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.