When does custom attribute constructor executes? - c#

Intention :
I am writing a business application that uses multiple enums where most of these enums exists in tables in the database too. The problem comes in maintenance when one of the team members or a late developer changes an enum member value at one of the two places leaving the enum unsynced. To solve this problem I am trying to create a custom enum attribute that throws some exception when it finds that an enum values are not in sync.
Implementation :
[AttributeUsage(AttributeTargets.Enum)]
public class EnumSyncAtrribute : Attribute
{
public EnumSyncAtrribute(Type databaseAccessType, Type enumType))
{
// Code that uses that databaseAccessType to access the database to get
// enum values then compare it to values of enumType , goes here.
}
}
Then target enum is marked as follows
[EnumSyncAtrribute(typeof(MyDataBaseAccess), typeof(MyEnum))]
public enum MyEnum
{
value1 = 0,
value2 = 1,
value3 = 2
}
Problem :
The problem is this attribute constructor never executes! I have tried replacing Enums with Classes and found that it executes fine, but with Enums, no!
The question is, when custom attributes are used for enums, when does their constructors executes?

The attribute is constructed only when you retrieve it (using the GetCustomAttribute function). Otherwise, its construction recipe (constructor overload + positional parameters + properties values) is only stored in the assembly metadata.
In your case, I'd retieve all enum types from the assembly, and check if they have the attribute. Something like that at the startup of your application:
var allEnumTypes = Assembly.GetExecutingAssembly()
.GetTypes()
.Where(t => t.IsEnum);
foreach(var enumType in allEnumTypes)
{
var syncAttr = Attribute.GetCustomAttribute(enumType, typeof(EnumSyncAtrribute)) as EnumSyncAtrribute;
if (syncAttr != null)
{
// Possibly do something here, but the constructor was already executed at this point.
}
}

Related

define a function to accept a specific list parameter

I want to define a function with a parameter, that paramter must be a specific, defined in a list (for example)
i remember doing this years ago but my memory has failed me.
example
public void foo(specific choice list defined in my class){}
specific-list = x,y,z
consume it list this (i think)
foo(myclass.x)
To expand on #kaffekopp's comment, it seems likely that you are talking about an enum, i.e.
public enum MyEnum // declare the enum type (optional: specify an underlying integer type)
{
Apple, // define the choices (note: enums are **not** strictly enforced;
Pear, // they are just named integers, and at runtime you can be surprised to find
Bicycle, // that the actual value is 42, a value you never defined)
}
with (on MyClass):
public MyEnum SomeProp {get;set;} // define a property as being of that enum type
and:
public void Foo(MyEnum option) {...} // define a method that takes a parameter of the type
then either:
Foo(MyEnum.Bicycle); // passing a constant/literal
or:
MyClass obj = ...
Foo(obj.SomeProp); // passing an existing value from somewhere

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). 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:
grandpa's horrible ugly switch statement
an array mapping the enum value to a Type
reflection-based magic mapping enum member name as string to class type elsewhere
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. 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.
I'd probably go for a custom attribute with a FormatsOutputFor property. Then decorate all of your implementations of IFormatOutput with the attribute. e.g.
[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...
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?

Should I be using generics to simplify my configuration provider class?

I am attempting to write a configuration manager that can supply configuration settings from different providers (e.g. settings files, environment variables, databases etc).
I have envisioned that the settings will be either strings, ints or doubles and will be identified by a name
Settings are provided via classes implementing this:
public interface IConfigurationManagerProvider
{
T GetSetting<T>(string name);
IEnumerable<ConfigurationSetting> GetKnownSettings();
}
As a start I am trying to write a provider to return environment variables
public class EnvironmentVariableProvider : IConfigurationManagerProvider
{
public T GetSetting<T>(string name)
{
string value = Environment.GetEnvironmentVariable(name);
return value as T;
}
public IEnumerable<ConfigurationSetting> GetKnownSettings()
{
return new List<ConfigurationSetting>
{
new ConfigurationSetting("MY_TRACING", typeof (String)),
};
}
}
however this won't compile as it can't cast to T.
If I put a class constraint in then this limits me to strings
public T GetSetting<T>(string name) where T : class
{
string value = Environment.GetEnvironmentVariable(name);
return value as T;
}
Really this provider can only supply strings (other providers will be different) however I want the code to access the configuration settings to be as clean as possible using something like:
public interface IConfigurationManagerConsumer
{
T GetConfiguration<T>(string name, T systemDefault);
}
and used like this:
string tracing = ConfigurationManager.GetConfiguration("MY_TRACING", "Unknown");
or this:
int maxUserCount = = ConfigurationManager.GetConfiguration("Max User Count", 10);
or this:
double pi = ConfigurationManager.GetConfiguration("PI", 3.14159);
Am I going in the right direction?
use Convert.ChangeType
return (T)Convert.ChangeType(value, typeof(T));
I have a vaguely similar variable provider interface, in which I didn't use generics. I started out with generics, and found that it didn't make the code any more readable or performant, particularly since the types were few and known from the start. After all, you're not getting anything dynamic, it is inferring the type from the default value you give. I also wanted my variable provider to be usable without providing a default value, and didn't want to use a different syntax for that.
So mine consists of two levels. One is public interface provider that I use in code, which can be used like in these examples:
IVariableProvider var;
// providing default value
double pi = var.Double["pi", 3.14159];
// no default value, also bool is just an int, converted by the IVariableProvider.
bool answer = var.Bool["answer"];
int number = var.Int["number"];
if(var.Str.ContainsKey("text"))
{
string text = var.Str["text"];
...
}
I could add public interfaces for var.Float, var.Long, etc if desired.
Underneath, the IVariableProvider can be given different "sources" to get variables from. The sources only expose string and integer. It can use other IVariableProviders as sources as well. When I call var.Double["pi"], it checks if any of the sources can provide a string variable for the key "pi" and then double.Parse() and return it.
Ultimately, you can do it either way. If you use generics like that and then want to use it without default values, you'll have to use different syntax in order to specify the type.

How to reflect a custom attribute applied to enum type itself

I've got a custom attribute that I want to apply to an enum type itself, but I'm having trouble identifying the correct path to get at the proper *Info in order to expose the attribute.
Something like this
[AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = true)]
public class MyCustAttribute : Attribute {}
[MyCust()]
[MyCust()]
[MyCust()]/*...and so on...*/
public enum MyEnumType{}
I am familiar with the more "customary" methods of reflecting say a DescriptionAttribute from an enumerated value. I do that sort of thing all the time, no problem. As in the following type case.
public enum MyEnumType {
[Description("My First Value")]
First,
[Description("My Second Value")]
Second,
}
I'm sure it's obvious, but I fail to see whether this is possible.
You can iterate over your custom attributes of an enum type like this:
static void Main(string[] args)
{
var attributes = typeof(MyEnumType).GetCustomAttributes(typeof(MyCustAttribute), false);
foreach (MyCustAttribute attribute in attributes)
Console.WriteLine("attribute: {0}", attribute.GetType().Name);
Console.ReadKey();
}
In this example, GetCustomAttributes returns an array of object. We use the ability of a foreach loop to cast up to the type we know the array elements contain because that's what we asked for: MyCustAttribute.
Since your custom attribute doesn't have anything interesting in it yet, we just chose to print out the name of the type. You'll obviously do something more exciting with your real instance of the type.

Multiple generic methods with identical names and arguments, but different results and constraints

I'm currently rewriting parts of a custom RPC mechanism (which cannot be replaced by something else, so don't suggest that ;-) ). The arguments of a call are collected in a custom collection that uses a dictionary internally. There is a method T Get<T>(string) to retrieve a named argument. For optional arguments, I wanted to add a TryGet<T>(string) method that returns the argument or null if it doesn't exist, so that the calling code can provide a default value using the null coalescing operator. Of course, for a value type this doesn't work, but I could use T? instead, which is what I want.
So what I have is this:
public class Arguments
{
// lots of other code here
public T TryGet<T>(string argumentName) where T : class
{
// look up and return value or null if not found
}
public T? TryGet<T>(string argumentName) where T : struct
{
// look up and return value or null if not found
}
}
With that, I'd like to be able to do the following:
return new SomeObject(
args.TryGet<string>("Name") ?? "NoName",
args.TryGet<int>("Index") ?? 1
);
Since the constraints are mutually exclusive, the compiler should be able to produce the correct code (it's always possible to infer the call from the generic type given at the call site). The compiler complains that the type already defines a member called "TryGet" with the same parameter types.
Is there any way to make something like this work without giving the two methods different names?
Constraints are not part of the signature. thus the answer to your question is no.
The way classes in the .NET Framework handle this scenario is TryGetValue with an out parameter. The return value is an indicator of whether the get was successful, where the out parameter contains the value requested (on success) or a suitable default value (on failure).
This pattern makes the implementation very simple for reference and value types. You would only need a single method to handle both scenarios.
For an example of this pattern, see Dictionary<TKey,TValue>.TryGetValue.
The reason this doesn't work is because you cannot have two methods with the same name and same argument types (the return type is not taken into account for method overloading). Instead you could define a single method without the generic constraint which will work for both value and reference types:
public T TryGet<T>(string argumentName)
{
if (!_internalDictionary.ContainsKey(argumentName))
{
return default(T);
}
return (T)_internalDictionary[argumentName];
}
An alternative solution could be this one:
public class Arguments {
public T Get<T>(string argumentName,T defaultValue) {
// look up and return value or defaultValue if not found
}
}
return new SomeObject(
args.Get<string>("Name","NoName"),
args.Get<int>("Index",1)
);
In that particular case you would not even have to specify the generic type, as it could be inferred by the default parameter:
return new SomeObject(
args.Get("Name","NoName"),
args.Get("Index",1)
);
Although it does not work directly due to identical argument types, You can do that by adding optional defaultValue parameter which defaults to null:
public class Arguments
{
// lots of other code here
public T? TryGet<T>(string argumentName, T? defaultValue = null) where T : class
{
// look up and return value or null if not found
}
public T? TryGet<T>(string argumentName, T? defaultValue = null) where T : struct
{
// look up and return value or null if not found
}
}
The reason this one works is that second argument type is different for both contraints (In the the method with class constraint it is simply T, and in the method with struct constraint it is Nullbale<T>).
Following code works as you would expect:
var args = new Arguments();
var stringValue = args.TryGet<string>("Name") ?? "NoName";
var intValue = args.TryGet<int>("Index") ?? 1;

Categories

Resources