I am in situation where I need to store a payment type enumeration value in the database for record keeping.
The problem is that I would like to add the ability for end user define their own value types.
I understand that I can use a negative range in my enumeration for my own values since user defined types will have an id greater than 0 but would that be a correct approach?
Or maybe I should have a second column like CustomPaymentType and referenced to PaymentType table for a data consistency?
Don't use an enumeration.
Enumerations are only useful for things that are constant by their nature, like days of the week.
Instead use a reference table in the data base like CustomPaymentType (Id,PaymentTypeName)
then you can use a class that looks like:
public class CustomPaymentType
{
public string paymentTypeName { get; private set; }
public int Id { get; private set; }
// if you need "Constant payment types usable in code, just add something like:
public static CustomPaymentType CashPayment
{
get { return new CustomPaymentType() { Id = 7, paymentTypeName= "CashPayment" } }
}
public static CustomPaymentType CreditPayment
{
get { return new CustomPaymentType() { Id = 7,paymentTypeName= "CreditPayment" } }
}
}
This approach is pretty good, because you have both the ease of coding about well known specific instances that you may need while coding, and its also very extendable.
Related
Consider the following code:
public interface IIdentifiable<T>
{
T Id { get; set; }
}
public interface IViewModel
{
}
public class MyViewModel1 : IViewModel, IIdentifiable<int>
{
public string MyProperty { get; set; }
public int Id { get; set; }
}
public class MyViewModel2 : IViewModel, IIdentifiable<string>
{
public string MyProperty { get; set; }
public string Id { get; set; }
}
I also have class that operates with ViewModels:
public class Loader<T> where T: IViewModel
{
public void LoadData()
{
/*some important stuff here*/
if (typeof(IIdentifiable<??>).IsAssignableFrom(typeof(T)))
{ // ^- here's the first problem
data = data.Where(d => _dataSource.All(ds => ((IIdentifiable<??>) ds).Id != ((IIdentifiable<??>) d).Id)).ToList();
} // ^---- and there the second ----^
/*some important stuff here too*/
}
}
Now, as you can see, viewmodels that I have might implement the IIdentifiable<> interface. I want to check that, and if it's true,
I want to make sure my data list does not contains any entry that are already present in my _dataSourse list.
So I have 2 questions:
I don't know what IIdentifiable<> has in its generic parentheses, it might be int, string or even GUID.
I tried typeof(IIdentifiable<>).IsAssignableFrom(typeof(T)) which is the correct syntax, yet it always returns false.
Is there a way to check whether T is IIdentifiable<> without knowing the exact generic type?
If there is an answer for the first question, I would also like to know how can I compare the Id fields without knowing their type.
I found this answer quite useful, yet it doesn't cover my
specific case.
I know that I probably can solve that problem if I make my Loader<T> class a generic for two types Loader<T,K>, where K would be the
type in IIdentifiable<>, yet I would like to know if there are other solutions.
P.S. In addition to my first question: I'm also curious why one can write something like this typeof(IIdentifiable<>).IsAssignableFrom(typeof(T)) if it returns false when the generic type of IIdentifiable<> is not specified?
Edit: I guess, in hindsight, I understand why I can't write the code this bluntly - because there's might be the collection ICollection<IViewModel> where the entries implement different types of IIdentifiable<> (or don't implement it at all), and the check like that would fail awkwardly. Yet maybe there is a way to do something like that with some restrictions, but without creating second generic parameter to my Loader?
Try add two methods to your Loader<T>:
public bool CanCast<TId>()
{
var identifiableT = typeof(IIdentifiable<>).MakeGenericType(typeof(TId));
return identifiableT.IsAssignableFrom(typeof(T));
}
public IEnumerable<IIdentifiable<TId>> Filter<TId>(IEnumerable<T> data)
{
return data.Where(d => _dataSource.All(
ds => !((IIdentifiable<TId>) ds).Id.Equals(((IIdentifiable<TId>) d).Id)));
}
Then in LoadData
if (CanCast<int>())
data = Filter<int>(data);
else if (CanCast<Guid>())
data = Filter<Guid>(data);
// and so om
Well, I would suggest you to always use a string for identification. You can convert int and guid to a string. And if you want to ensure proper type is used then you can prefix the string with type information.
However, I do think that the performance of you algorithm would be very poor as you wouls essentially loop 2 containers so it would be O(n * m).
Thus it would be best to either do appropriate SQL query if both sources are from the database or use a dictionary if you do it in code. Alternatively if data is properly sorted, you could find duplicates more efficiently.
By the way generics are quite limited in C#. Sometime using ˋFunc<>ˋ could help but even then you have to provide extra information to the algorithm.
We should address your question in two steps (because there really are two problems to solve here).
First, make following change to your interface IIdentifiable<T>
public interface IIdentifiable<T>
where T : IEquatable<T>
{
T Id { get; set; }
}
This will ensure that you can compare Id properties correctly.
Secondly, in your LoadData() method, change the if statement to
if (T is IIdentifiable<T>)
{ // ^- here's the first problem
data = data.Where(d => _dataSource.All(ds => ((IIdentifiable<T) ds).Id != ((IIdentifiable<T) d).Id)).ToList();
}
We can pass data between functions by using class objects. Like i have class
public class AddsBean
{
public long addId{get;set;}
public int bid { get; set; }
public long pointsAlloted { get; set; }
public string userId { get; set; }
public enum isApproved { YES, NO };
public DateTime approveDate { get; set; }
public string title { get; set; }
public string description { get; set; }
public string Link { get; set; }
public DateTime dateAdded { get; set; }
}
We can call function like public List<AddsBean> getAdds(string Id). This approach is good when you need all the variables of class. But what if you need only 2 or 3 variables of class?
Passing object of class is not good because it will be wastage of memory. Another possible solution is to make different classes of lesser variables but that is not practical.
What should we do that will best possible solution to fulfill motive and best according to performance also?
In Java - "References to objects are passed by value".. So, you dont pass the entire object, you just pass the reference to the object to the called function.
EG:
class A{
int i;
int j;
double k;
}
class B{
public static void someFunc(A a) // here 'a' is a reference to an object, we dont pass the object.
{
// some code
}
public static void main(String[] args){
A a = new A();
B.someFunc(a); // reference is being passed by value
}
}
first of all, as Java is pass by value and references typed, there is no need to worry about the memory wastage.
next, as you have mentioned, it is not good to pass all the object if you do not need them all, in some situation, it's true. as you need to protect your data in instance, thus you can use different granularity of class, for instance:
class A
{id, name}
class B extends A
{password,birthday}
by refer to different class you can control the granularity yourself, and provide different client with different scope of data.
But in some condition, you need to use a instance to store all data in the whole application, like configure data in hadoop, or some other configuration related instance.
Try to choose the most suitable scope!
If you're sure that this is the source of problems and you don't want to define a new class with a subset of the properties, .NET provides the Tuple class for grouping a small number of related fields. For example, a Tuple<int, int, string> contains two integers and a string, in that order.
public Tuple<string, long, DateTime> GetPointsData()
{
AddsBean bean = ... // Get your AddsBean somehow
return Tuple.Create<string, long, DateTime>(bean.userId, bean.pointsAlloted, bean.approveDate);
}
Once this method goes out of scope, there is no longer a live reference to the object bean referred to and will be collected by the garbage collector at some point in the future.
That said, unless you're sure that instances of the AddsBean class are having a noticeable negative effect on the performance of your app, you should not worry about it. The performance of your application is probably affected far more by other operations. Returning a reference type (a type defined with class instead of struct) only passes a reference to the object, not the data of the object itself.
I am working on ASP.NET MVC 4 application even though for this exact problem I think it's irrelevant. I am using EF 5 with Code First and I have entity Menu where a menu can be one of four different types. In my entity the type of the menu is declared as
public class Menu
{
//other properties
public int Type { get; set; }
}
and I have declared the different types as constants:
public static class MenuType
{
public const int Report = 10;
public const int Contract = 20;
public const int Taxes = 30;
public const int Interests = 40;
}
So if I want to get all Menus from Contract type I have this:
unitOfWork.MenuRepository.GetAll().Where(x => x.Type == MenuType.Contract).ToList();
even though it's working OK I want to change this with enum values, I've tried this:
public static class MenuType
{
public static enum Types
{
Report = 10,
Contract = 20,
Taxes = 30,
Interests = 40
}
}
But then to retrieve the same records from above my code is:
unitOfWork.MenuRepository.GetAll().Where(x => x.Type == (int)(MenuType.Types.Contract)).ToList();
a lot more unreadable and more to write as well. I've seen enums to be used in a way similar to the way I use the constants. I'm not sure, maybe I have to implement additional method.
However how I can change the constants with enum values without making the queries more unreadable? Maybe some additional method like MenuTypeValue("Contract")...
You would have to change the type of the property on the Menu class to match the new enum you declared
public class Menu
{
//other properties
public Types Type { get; set; }
}
This way you will be comparing an enum to an enum and your code will become nice and clear again.
If you cannot do that, you will be probably better off with sticking to int constants or you will need to cast between int and the enum type all the time.
Change type of property "Type" in your model to enum. EF5 smart enough to internally convert it to int.
Take a look here: http://msdn.microsoft.com/en-us/data/hh859576.aspx
If what you're trying to do is make it more readable, why not move the logic into the repository class.
So you could make a call:
unitOfWork.MenuRepository.GetAll(MenuType.Type.Contract);
Then in your repository just have a method such as:
List<...> GetAll(MenuType.Type type = null) { ... }
So now you can still call GetAll without the type as it's an optional param but in that method you can work out what you need to be returning. Your calls will look cleaner then.
Suppose you need to store some values in a table formed by several columns (such as a relational database): for example, int for the first column, string for the second one, DateTime for the third one, etc..
If one or more column are like a primary key, then we could use an IDictionary, whose Key would be the set of fields that acts as a primary key. The remaining fields represent the Value. In this case I could create one or two classes/structures. For example, if the primary key is simply an existing type, we will only have to create a class/struct like the following:
public class MyValue
{
public int Field1;
public double Field2;
public string Field3;
}
The dictionary could be a Dictionary<int, MyValue>, while the table could be the following.
public class MyTable
{
private Dictionary<int, MyValue> _table;
...
}
Obviously, according to the application domain there may be ranges and/or rules of validity for the above fields: for example, Field1 may have to be positive, and so on...
As a first alternative I could design the MyValue class so that it throws some exceptions in order to identify the "violation of rules". But perhaps this approach might be excessive, especially if the class MyValue is used only internally to MyTable: in this case I would write code like the following and handle validity error within MyTable class: that is, MyTable class checks the data fields before inserting them into the dictionary, so MyValue would be a "stupid" class...
namespace MyNamespace
{
class MyValue
{
// only public fields
}
public class MyTable
{
private Dictionary<int, MyValue> _table;
...
public void Add(int key, int field1, double field2, string field3)
{
// some code to check validity range for fields
...
}
}
}
Is this solution correct? Or should I avoid this approach? Should I always define a class/struct in a complete manner (exceptions handling, Equals, GetHashCode methods?
What you've done looks overly complicated, brittle and will ultimately lead to maintainability nightmares.
I'd say you have two options.
Option one: use a DataTable. It doesn't have to be backed by an actual database and you can define it's layout (including column definitions) at runtime.
Option two: Define a class that implements your "record" logic. Define a Collection to hold that class. Use LINQ to "query" the collection for whatever you need.
The primary difference between the two options is that a DataTable is very limited in the type of rules you can employ. Option 2, OTOH, allows you to build precisely what you want.
I would let the values check their consistency themselves. If you implement the fields as properties, the setter can do checks and throw an exception is the value is out of range for instance.
I also would suggest a somewhat more flexible approach. Define an interface that your table records must implement
public interface IRecord<PK>
{
PK ID { get; }
}
Records must have an ID, which will be used as primary key. We use a generic primary key type PK.
Now you can define a value class like this
public class MyValue : IRecord<int>
{
private int _field1;
public int Field1
{
get { return _field1; }
set
{
if (value < 0 || value > 1000) {
throw new ArgumentException("Value of 'Field1' must be between 0 and 1000");
}
_field1 = value;
}
}
public double Field2;
#region IRecord<int> Members
public int ID { get { return Field1; } }
#endregion
}
As you can see, it implements IRecord<int> and returns Field1 as ID. Field1 checks the values passed to it. If the primary key is made up of several fields you can use a type like Tuple (.NET 4.0) as primary key type. Like IRecord<Tuple<int,double>>.
Now you can define a generic table
public class Table<T, PK>
where T : IRecord<PK>
{
private Dictionary<PK, T> _table = new Dictionary<PK, T>();
public void Add(T item)
{
_table.Add(item.ID, item);
}
}
You can define specific tables like this
public class MyTable : Table<MyValue, int>
{
}
UPDATE:
Alternatively, you could let records implement an explicit error handling
public interface IRecord<PK> {
PK ID { get; }
bool IsValid { get; }
string[] Errors { get; }
}
I have an attribute in my car class called VehicleType.
Using an enum, I could list the different types of cars that exist and not allow any other type to be hard written in.
Problem is, if I have to GET the attribute from somewhere else, I will GET a numberical value, and not the string literal I saved.
What should I use here?
class Hero
{
public string faction;
public string name;
public string herotype;
enum HeroType
{
Agility,
Strength,
Intelligence,
}
}
You could create an abstract base class
public abstract class BaseHero
{
public string faction;
public string name;
...... more properties
}
and then derive your heroes from that:
public class AgilityHero : BaseHero
{
}
public class StrengthHero : BaseHero
{
}
public class IntelligenceHero : BaseHero
{
}
Common stuff would be handled and coded in the base class, those things specific to a hero type in the actual hero class.
Using this OO approach, you can save yourself from having to write, code, maintain a lot of if....then.....else or switch statements in your Hero class - the differences are handled by the fact of having different types for each type of hero.
What? Why would you have a string literal and an enum? Your class should look like this:
class Hero
{
public string faction;
public string name;
public HeroType herotype; // <-- not a string
enum HeroType
{
Agility,
Strength,
Intelligence,
}
}
The "string" version is just the enum so it's easier for you to remember, but shouldn't actually be saved as a string anywhere (except if you need to display it to the user).
Whether an enum is approriate depends entirely on your design. If you have a fixed number of possible values, then an enum may be a good approach.
In C# you can convert between an Enumerated type and its string representation using Enum.ToString() and Enum.Parse(), so it is trivially easy to serialise an enum's value and disallow "illegal" values when reloading the data. There is no need to serialise it as an integer value.
(The one caveat of this is if you use obfuscation, you must make sure not to obfuscate the enumerated type)
If you have to store the enum as an integer value, then there is no problem with that, as long as you don't change the values of the enum entries - add new entries at the end of the enum's list, but don't insert new entries in the middle of it.
What I sometimes do for modeling richer 'enumeration-like' types is the following:
public enum HeroTypeValue
{
Agility,
Strength,
Intelligence
}
public class HeroType
{
public HeroTypeValue Value { get; set; }
public string Description { get; set; }
// ... other properties and possibly behaviour, as needed
public static HeroType Agility = new HeroType
{
ID = HeroTypeValue.Agility,
Description = "Agility"
},
public static HeroType Strength = new HeroType
{
ID = HeroTypeValue.Strength,
Description = "Agility"
};
public static HeroType Intelligence = new HeroType
{
ID = HeroTypeValue. Intelligence,
Description = "Intelligence"
};
public static IEnumerable<HeroType> All = new []
{
Agility,
Strength,
Intelligence
}
}
This allows to do data binding with easily customizable descriptions, when needed you can also synchronize with a table in the database.
You can of course combine it with the answer by marc_s, making the HeroType a (abstract or not) base class for added OO value.