I have a table which maps String->Integer.
Rather than create an enum statically, I want to populate the enum with values from a database. Is this possible ?
So, rather than delcaring this statically:
public enum Size { SMALL(0), MEDIUM(1), LARGE(2), SUPERSIZE(3) };
I want to create this enum dynamically since the numbers {0,1,2,3} are basically random (because they are autogenerated by the database's AUTOINCREMENT column).
No. Enums are always fixed at compile-time. The only way you could do this would be to dyamically generate the relevant bytecode.
Having said that, you should probably work out which aspects of an enum you're actually interested in. Presumably you weren't wanting to use a switch statement over them, as that would mean static code and you don't know the values statically... likewise any other references in the code.
If you really just want a map from String to Integer, you can just use a Map<String, Integer> which you populate at execution time, and you're done. If you want the EnumSet features, they would be somewhat trickier to reproduce with the same efficiency, but it may be feasible with some effort.
So, before going any further in terms of thinking about implementation, I suggest you work out what your real requirements are.
(EDIT: I've been assuming that this enum is fully dynamic, i.e. that you don't know the names or even how many values there are. If the set of names is fixed and you only need to fetch the ID from the database, that's a very different matter - see Andreas' answer.)
This is a bit tricky, since the population of those values happens at class-load time. So you will need a static access to a database connection.
As much as I value his answers, I think Jon Skeet may be wrong this time.
Take a look at this:
public enum DbEnum {
FIRST(getFromDb("FIRST")), SECOND(getFromDb("second"));
private static int getFromDb(String s) {
PreparedStatement statement = null;
ResultSet rs = null;
try {
Connection c = ConnectionFactory.getInstance().getConnection();
statement = c.prepareStatement("select id from Test where name=?");
statement.setString(1, s);
rs = statement.executeQuery();
return rs.getInt(1);
}
catch (SQLException e) {
throw new RuntimeException("error loading enum value for "+s,e);
}
finally {
try {
rs.close();
statement.close();
} catch (SQLException e) {
//ignore
}
}
throw new IllegalStateException("have no database");
}
final int value;
DbEnum(int value) {
this.value = value;
}
}
Improving on what Andreas did, you can load the contents of the database into a map to reduce the number of database connections needed.
public enum DbEnum {
FIRST(getFromDb("FIRST")),
SECOND(getFromDb("second"));
private Map<String,Integer> map;
private static int getFromDB(String s)
{
if (map == null)
{
map = new HashMap<String,Integer>();
// Continue with database code but get everything and
// then populate the map with key-value pairs.
return map.get(s);
}
else {
return map.get(s); }
}
}
Enums are not dynamic, so the short answer is that you can't do it.
Also have a look at Stack Overflow question Dynamic enum in C#.
You need to replicate in code what is in the database (or vice-versa). See this question for some good advices.
In all the languages I know enums are static. The compiler can make some optimizations on them. Therefore the short answer is no, you can't.
The question is why you want to use an enum in this way. What do you expect?
Or in other words why not use a collection instead?
Related
Core Question:
I have a generic interface IValidatingAttribute<T>, which creates the contract bool IsValid(T value); The interface is implemented by a variety of Attributes, which all serve the purpose of determining if the current value of said Field or Property they decorate is valid per the interface spec that I'm dealing with. What I want to do is create a single validation method that will scan every field and property of the given model, and if that field or property has any attributes that implement IValidatingAttribute<T>, it should validate the value against each of those attributes. So, using reflection I have the sets of fields and properties, and within those sets I can get the list of attributes. How can I determine which attributes implement IValidatingAttribute and then call IsValid(T value)?
background:
I am working on a library project that will be used to develop a range of later projects against the interface for a common third party system. (BL Server, for those interested)
BL Server has a wide range of fairly arcane command structures that have varying validation requirements per command and parameter, and then it costs per transaction to call these commands, so one of the library requirements is to easily define the valdiation requirements at the model level to catch invalid commands before they are sent. It is also intended to aid in the development of later projects by allowing developers to catch invalid models without needing to set up the BL server connections.
Current Attempt:
Here's where I've gotten so far (IsValid is an extension method):
public interface IValidatingAttribute<T>
{
bool IsValid(T value);
}
public static bool IsValid<TObject>(this TObject sourceObject) where TObject : class, new()
{
var properties = typeof(TObject).GetProperties();
foreach (var prop in properties)
{
var attributeData = prop.GetCustomAttributesData();
foreach (var attribute in attributeData)
{
var attrType = attribute.AttributeType;
var interfaces = attrType.GetInterfaces().Where(inf => inf.IsGenericType).ToList();
if (interfaces.Any(infc => infc.Equals(typeof(IValidatingAttribute<>))))
{
var value = prop.GetValue(sourceObject);
//At this point, I know that the current attribute implements 'IValidatingAttribute<>', but I don't know what T is in that implementation.
//Also, I don't know what data type 'value' is, as it's currently boxed as an object.
//The underlying type to value will match the expected T in IValidatingAttribute.
//What I need is something like the line below:
if (!(attribute as IValidatingAttribute<T>).IsValid(value as T)) //I know this condition doesn't work, but it's what I'm trying to do.
{
return false;
}
}
}
return true;
}
}
Example usage:
Just to better explain what I am trying to achieve:
public class SomeBLRequestObject
{
/// <summary>
/// Required, only allows exactly 2 alpha characters.
/// </summary>
[MinCharacterCount(2), MaxCharacterCount(2), IsRequired, AllowedCharacterSet(CharSets.Alpha))]
public string StateCode {get; set;}
}
And then, later on in code:
...
var someBLObj = SomeBLRequestObjectFactory.Create();
if(!someBLObj.IsValid())
{
throw new InvalidObjectException("someBLObj is invalid!");
}
Thank you, I'm really looking for a solution to the problem as it stands, but I'm more than willing to listen if somebody has a viable alternative approach.
I'm trying to go generic extension method with this because there are literally hundreds of the BL Server objects, and I'm going with attributes because each of these objects can have upper double digit numbers of properties, and it's going to make things much, much easier if the requirements for each object are backed in and nice and readable for the next developer to have to use this thing.
Edit
Forgot to mention : This Question is the closest I've found, but what I really need are the contents of \\Do Something in TcKs's answer.
Well, after about 6 hours and a goods nights sleep, I realized that I was over-complicating this thing. Solved it with the following (ExtValidationInfo is the class that the below two extensions are in.):
Jon Skeet's answer over here pointed me at a better approach, although it still smells a bit, this one at least works.
public static bool IsValid<TObject>(this TObject sourceObject) where TObject : class, new()
{
var baseValidationMethod = typeof(ExtValidationInfo).GetMethod("ValidateProperty", BindingFlags.Static | BindingFlags.Public);
var properties = TypeDataHandler<TObject>.Properties;
foreach (var prop in properties)
{
var attributes = prop.GetCustomAttributes(typeof(IValidatingAttribute<>)).ToList();
if (!attributes.Any())
{
continue; // No validators, skip.
}
var propType = prop.PropertyType;
var validationMethod = baseValidationMethod.MakeGenericMethod(propType);
var propIsValid = validationMethod.Invoke(null, prop.GetValue(sourceObject), attributes);
if(!propIsValid)
{
return false;
}
}
return true;
}
public static bool ValidateProperty<TPropType>(TPropType value, List<IValidatingAttribute<TPropType>> validators)
{
foreach (var validator in validators)
{
if (!validator.IsValid(value))
{
return false;
}
}
return true;
}
I need to validate a field's value according to two different validation rules:
An object of my own which contains a regex and a range (for string it's length range).
A list of possible values.
So I can do this:
public static bool Validate(string fieldValue, string fieldType, ValidationParameters validationParameters)
{
...
}
public static bool Validate(string fieldValue, string fieldType, string[] possibleValues)
{
...
}
But that requires the user to ungracefully if.
I can also do this:
public static bool Validate(string fieldValue, string fieldType, ValidationParameters validationParameters=null,string[] possibleValues=null)
{
...
}
Now the user can just send he's data, without redundant if, But I can't make sure validationParameters or possibleValues (one of them) got a value.
Is there a third option, one in which the user won't have to check which method he uses, but I won't have to worry that he doesn't send any of the two fields (in code, not documentation)?
If not, which way of the two above is better (less error-prone and more elegant)?
Thanks.
I personally would do two overloaded methods. The main reasoning for this is:
But I can't make sure validationParameters or possibleValues (one of them) got a value.
Optional arguments, in my opinion, should be exactly that: optional. Making two optional arguments where one is required seems like a problematic design choice.
Your main reasoning for avoiding this seems to be:
But that requires the user to ungracefully if.
However, I don't see the problem. The user is going to have to construct either the string collection (which, I personally, would either make IEnumerable<string> instead of string[], or do params string[] possibleValues) or the ValidationParameters. If they already need to construct the arguments to pass, adding an if conditional seems unnecessary (each path could just call the validation).
If they are validating by different concepts, they should probably be named differently. Say, ValidateByValidationParameters and ValidateByPossibleValues. Now the question is, why wouldn't you want the caller to carefully select which one he is using?
Because you can't require that one of them is sent, I'd recommend the former option, but I don't understand what you mean by the fact that you don't like that the user has to "ungracefully if".
You can overload the methods - as you said - or do something like this:
enum TYPE { VAL_1, VAL_2 }
void function(TYPE validateType, object o)
{
swich(validateType)
{
case VAL_1:
List<string> par = o List<String>;
if(par != null)
{
//...
}
break;
case VAL_2:
List<MyObject> par = o as List<MyObject>;
if(par != null)
{
//...
}
break;
}
}
Maybe it's not very typesafe, but somteimes useful.
At last - you can prepare single delegate method for every validation case and call those methods (single or many) in one place.
I have a CacheHelper class to facilitate interaction with the cache. I want to use a static int field to specify my cache timeout. The field is initially set to a const default value but I want to provide a way for the application to change the default timeout value.
Do you need to lock when modifying a static value type? Is the lock in the setter necessary? Are there any other problems you can see here? Sorry, I'm still pretty dumb when it comes to multithreading.
Thanks.
public static class CacheHelper
{
private static object _SyncRoot;
private static int _TimeoutInMinutes = CacheDefaults.TimeoutInMinutes;
public static int TimeoutInMinutes
{
get
{
return _TimeoutInMinutes;
}
set
{
lock (_SyncRoot)
{
if (_TimeoutInMinutes != value)
{
_TimeoutInMinutes = value;
}
}
}
}
public static void Insert(string key, Object data)
{
if (HttpContext.Current != null && data != null)
{
HttpContext.Current.Cache.Insert(key, data, null, Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(CacheHelper.TimeoutInMinutes));
}
}
}
You could use a volatile variable instead... but you need something, otherwise it's possible that a value written by one thread would never be seen by another.
Note that for "larger" types such as double or long you really should use a lock or the Interlocked class, as modifications to those values may not be atomic.
You don't need to lock here if the client of CacheHelper does somthing like
CacheHelper.TimeoutInMinutes = input.Value;
Since it doesn't rely on the previous value.
If your client does something like
CacheHelper.TimeoutInMinutes += input.Value;
Then you'll need to do some locking
.
I have a function that returns objects of different types based on the parameter passed to this function.
Is it possible to add these different object types to a collection based on some identifier in C# 4.0?
Usually we do something like this
List or List
but i want one collection which can add object of any type.
Instead of just making a List<object> like other posters are recommending, you may want to define an interface eg IListableObject that contains a few methods that your objects need to implement. This will make any code using these objects much easier to write and will guard against unwanted objects getting into the collection down the line.
Yes, it is called object. Eg:
var objlist = new List<object>();
objlist.Add(1);
objlist.Add(true);
objlist.Add("hello");
You could use object[], List<object>, ArrayList, IEnumerable, ... but if those types have a common base type it would be better to stick to a strongly typed collection.
Really your collection should be as specific as you can make it. When you say
objects of different types
Do these objects have anything in common? Do they implement a common interface?
If so you you can specialise the list on that interface List<IMyInterface>
Otherwise List<object> will do what you want.
Update
No, not really.
I'm sorry but I'm going to question your design.
If you have a collection of different objects, how do you decide how to use one of the objects?
You're going to have a large switch statement switching on the type of the object, then you cast to a specific object and use it.
You also have have a similar switch statement in your factory method that creates the object.
One of the benefits of Object Orientation is that if you design your objects correctly then you don't need to do these large "If it's this object do this.Method(), if it's that object do that.OtherMethod()".
Can I ask, why are you putting different objects into the same collection? What's the benefit to you?
If you want a collection which can add objects of any type then List<object> is the most appropriate type.
Collections in earlier versions of C# (not generics) can contain any kind of objects. If they're value type, they will be boxed into object.
When you need to use them, you can just cast it to the original type.
You may use List<Type> to hold the type information, if that's what you want. And Type[], Hashtable, etc. are also fine. You can use typeof operator to get the type or use Object.GetType().
Also check out Dynamic type.
http://msdn.microsoft.com/en-us/library/dd264736.aspx
It will basically do the same thing.
My Suggestion:
public class ParamValue
{
object value = null;
public ParamValue(object val)
{
value = val;
}
public string AsString()
{
return value.ToString();
}
public int AsInt()
{
return int.Parse(value.ToString());
}
public int? AsNullableInt()
{
int n;
if (int.TryParse(value.ToString(), out n))
{
return n;
}
return null;
}
public bool AsBool()
{
return bool.Parse(value.ToString());
}
public bool? AsNullableBool()
{
bool b;
if (bool.TryParse(value.ToString(), out b))
{
return b;
}
return null;
}
}
public class Params
{
Dictionary<string, object> paramCol = new Dictionary<string, object>();
public void Add(string paramName, object value)
{
paramCol.Add(paramName, value);
}
public ParamValue this[string paramName]
{
get
{
object v;
if (paramCol.TryGetValue(paramName, out v))
{
return new ParamValue(v);
}
return null;
}
}
}
Use param class as a collectio to your values, you can convert the return to every type you want.
You could use a Tuple of Genric Types
public Tuple<T, T> MySuperMethod()
{
int number = 1;
string text = "Batman";
return new Tuple<int, string>(number, text);
}
The .NET Framework directly supports tuples with one to seven
elements. In addition, you can create tuples of eight or more elements
by nesting tuple objects in the Rest property of a Tuple object.
https://msdn.microsoft.com/en-us/library/system.tuple(v=vs.100).aspx
I know that the Specification pattern describes how to use a hierarchy of classes implementing ISpecification<T> to evaluate if a candidate object of type T matches a certain specification (= satisfies a business rule).
My problem : the business rule I want to implement needs to evaluate several objects (for example, a Customer and a Contract).
My double question :
Are there typical adaptations of the Specification patterns to achieve this ? I can only think of removing the implementation of ISpecification<T> by my specification class, and taking as many parameters as I want in the isSatisfiedBy() method. But by doing this, I lose the ability to combine this specification with others.
Does this problem reveal a flaw in my design ? (i.e. what I need to evaluate using a Customer and a Contract should be evaluated on another object, like a Subscription, which could contain all the necessary info) ?
In that case (depending on what the specification precisely should do, I would use one of the objects as specification subject and the other(s) as parameter.
Example:
public class ShouldCreateEmailAccountSpecification : ISpecification<Customer>
{
public ShouldCreateEmailAccountSpecification(Contract selectedContract)
{
SelectedContract = selectedContract;
}
public Contract SelectedContract { get; private set; }
public bool IsSatisfiedBy(Customer subject)
{
return false;
}
}
Your problem is that your specification interface is using a generic type parameter, which prevents it from being used for combining evaluation logic across different specializations (Customer,Contract) because ISpecification<Customer> is in fact a different interface than ISpecification<Contract>. You could use Jeff's approach above, which gets rid of the type parameter and passes everything in as a base type (Object). Depending on what language you are using, you may also be able to pull things up a level and combine specifications with boolean logic using delegates. C# Example (not particularly useful as written, but might give you some ideas for a framework):
ISpecification<Customer> cust_spec = /*...*/
ISpecification<Contract> contract_spec = /*... */
bool result = EvalWithAnd( () => cust_spec.IsSatisfiedBy(customer), () => contract_spec.IsSatisfiedBy( contract ) );
public void EvalWithAnd( params Func<bool>[] specs )
{
foreach( var spec in specs )
{
if ( !spec() )
return false; /* If any return false, we can short-circuit */
}
return true; /* all delegates returned true */
}
Paco's solution of treating one object as the subject and one as a parameter using constructor injection can work sometimes but if both objects are constructed after the specification object, it makes things quite difficult.
One solution to this problem is to use a parameter object as in this refactoring suggestion: http://sourcemaking.com/refactoring/introduce-parameter-object.
The basic idea is that if you feel that both Customer and Contract are parameters that represent a related concept, then you just create another parameter object that contains both of them.
public class ParameterObject
{
public Customer Customer { get; set; }
public Contract Contract { get; set; }
}
Then your generic specification becomes for that type:
public class SomeSpecification : ISpecification<ParameterObject>
{
public bool IsSatisfiedBy(ParameterObject candidate)
{
return false;
}
}
I don't know if I understood your question.
If you are using the same specification for both Customer and Contract, this means that you can send the same messages to both of them. This could be solved by making them both to implement an interface, and use this interface as the T type. I don't know if this makes sense in your domain.
Sorry if this is not an answer to your question.