简体   繁体   English

C#:基于整数Enu​​m值创建类型的实例

[英]C#: Create instance of a type based on an integral Enum value

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). 因此, SomeFormattableEntity通过Dapper SomeFormattableEntity在数据库中,其OutputType属性存储为基础整数值(即,在INT列中)。 As you can guess, I want to provide an instance of a IFormatOutput to handle a SomeFormattableEntity based on its OutputType property. 如您所料,我想提供一个IFormatOutput实例来根据其OutputType属性处理SomeFormattableEntity

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: 到目前为止,我的想法包括建立一家具有潜在内部影响的工厂:

  1. grandpa's horrible ugly switch statement 爷爷的丑陋开关声明
  2. an array mapping the enum value to a Type 将枚举值映射到Type的数组
  3. reflection-based magic mapping enum member name as string to class type elsewhere 基于反射的魔术映射枚举成员名称作为其他类类型的字符串
  4. some mapping mechanism involving attributes 一些涉及属性的映射机制

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. 我意识到,不要求要求其类型基于值的事物的实例,但是在涉及SQL时似乎很难避免这种情况。 Basically the problem is that multiple "things" that all have varying .NET types are stored in a single table. 基本上,问题是所有都具有不同.NET类型的多个“事物”存储在单个表中。 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. 我可能会选择带有FormatsOutputFor属性的自定义属性。 Then decorate all of your implementations of IFormatOutput with the attribute. 然后,使用属性装饰IFormatOutput所有实现。 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 . 您可能想要构建一些内部缓存,以将OutputFormat值映射到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. 然后,您的工厂可以再次检查您是否只有一种类型映射到每种输出格式,如果您尝试为没有对应类的枚举值获取格式化程序,则不会从激活器中得到一些晦涩的TypeLoadException。

Hopefully that makes sense... 希望这是有道理的...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM