Reputation: 770
I'm currently trying to assign the names in a particular enum to a string so that I can use it in the help documentation that is output to the console. This is easy enough to do via:
public string names = string.Join(", ", Enum.GetNames(typeof(LicenseType)));
My problem is that I'm using the Command Line Parser Library, which requires the help text for each option to be specified as an attribute argument (HelpText
), which must be a "constant expression, typeof expression or array creation expression of an attribute parameter type". Example of how names
would be used:
[Option('t', "license-type", Required = true, HelpText = names)]
However, when I try and assign the enum names to a const string
using the above code, the compiler complains that the expression is not constant.
Is there any way around this?
Upvotes: 1
Views: 2016
Reputation: 10708
EDIT This can now be achieved using the nameof
operator, albeit only by referencing each object one by one at compile time.
The problem is that even though enum
s might be compile-time constants, any code, including the above code to actually get those names, is not constant, since it requires evaluation beyond simply being a primitive. Thus, it is not possible to use an enum
name in an Attribute
which expects a string
.
IF, however, the OptionAttribute
is not sealed
, you could define an inherited Attribute
class which takes a parameter of the desired Enum, and then passes the above code to base(string)
. Using this Attribute
, the library should see it as a OptionAttribute
, even though you've handed it an enum
value. See the following code:
public class EnumHelpTextAttribute // Always postpend the word "Attribute" to an attribute class
// The compiler cleans this suffix when you actually use the Attribute
: OptionAttribute
{
public EnumHelpTextAttribute(LicenseType value)
: base(string.Join(", ", Enum.GetName(typeof(LicenseType), value)))
{
}
}
// ...
[EnumHelpText(LicenseType.Restricted)] // Or some other value in LicenseType...
Sadly, it has been noted that the OptionAttribute
class is sealed
, which prevents inheritors from being created. Being an open-source project however, it is possible to fork the source, unseal the class, and use the above suggestion thusly. As always, document the usage and make a pull request back - this could easily save someone else the trouble one day!
Upvotes: 3
Reputation: 770
After sleeping on it last night, the solution was actually pretty obvious (ain't it always the way!): just use string replacement...
class Options
{
private static string LicenseTypeHelp = "License type (" + string.Join(", ", Enum.GetNames(typeof(CompanyLicenseType))) + ").";
[Option('t', "license-type", Required = true, HelpText = "License type.")]
public CompanyLicenseType LicenseType { get; set; }
[HelpOption('h', "help", HelpText = "Dispaly this help screen.")]
public string GetUsage()
{
string helpText = HelpText.AutoBuild(this, current => HelpText.DefaultParsingErrorsHandler(this, current));
return helpText.Replace("License type.", LicenseTypeHelp);
}
}
Upvotes: 0
Reputation: 149518
Enums are compile time constants, but the compiler has no guarantee that a method call to string.Join
will yield a constant value because it is being used with an Enum.GetName
.
As your enum is a compile to constant, you will need to hardcode the values to your attributes.
Upvotes: 0