I'm working with an older Oracle database, and I feel there's likely a better way to go about unboxing the values I retrieve from the database.
Currently, I have a static class full of different type-specific methods:
public static int? Int(object o)
{
try
{
return (int?)Convert.ToInt32(o);
}
catch (Exception)
{
return null;
}
}
..and so on for different types, but I feel there should be a better way? If I want to unbox a value, I do something along the lines of...
int i;
i = nvl.Int(dataRow["column"]); //In this instance, "column" is of a numeric database type
I thought about using a generic class to handle all the different types, but I couldn't really figure out the best way to go about that.
Any ideas?
I find helper methods such as the following useful in your scenario - testing for DBNull is more efficient than catching an Exception as in your example:
public static MyHelper
{
public static Nullable<T> ToNullable<T>(object value) where T : struct
{
if (value == null) return null;
if (Convert.IsDBNull(value)) return null;
return (T) value;
}
public static string ToString(object value)
{
if (value == null) return null;
if (Convert.IsDBNull(value)) return null;
return (string)value;
}
}
This works for the string and the usual primitive value types you will encounter (int, decimal, double, bool, DateTime).
It's slightly different from your example in that it casts rather than converts - but personally I prefer this. I.e. if the database column is NUMERIC (decimal), I'd rather be explicit if I wanted to convert the value to int, e.g.:
int? myIntValue = (int?) MyHelper.ToNullable<decimal>(reader["MyNumericColumn"]);
You could introduce simple model classes and map between them.
For example:
public class Customer
{
public Customer(DataRow row)
{
Name = row["Name"];
}
public Name { get; private set; }
}
Of course, to reduce duplicate code, you could create a base class for your model data classes.
Depending on effort you want to spend, you could go and use an ORM mapper NHibernate.
Related
I have a bit of a strange issue here. I have a project constraint where a value of a Property needs to either be a number (int, double, long, etc are all acceptable), a string, or a datetime. The reason that the Value parameter needs to be of one these three (err..well if you count all of the possible numeric value Types allowed it's a bit more) Types is because depending on the type the underlying value will need to be converted to special formats for serialization to a REST API. To simplify things here is a basic idea of the class as a POCO:
class Foo
{
public string Name {get;set;}
public Guid Id {get; set;}
public UNKNOWN Value {get;set;}
}
I thought about using generics for this, with a where T : struct constraint, but this still leaves too many types that can theoretically be set that are actually invalid Types. Sure I can perform type checking and throw exceptions during construction/setting of the Value parameter, but this doesn't feel like "clean" code.
I took a look at this question How do you work with a variable that can be of multiple types? , but it didn't really help since it was more of an issue dealing with inheritance. However, using multiple nullable private fields and returning a single Property based on which one was populated is a possibility, but again I feel there has to be a better way.
The other possibility I was thinking of was to use the dynamic type and and perform some reflection magic to check the underlying type (and perform conversions & formatting/throw exceptions). I'm a bit scared that this will really hurt performance though.
Are there any best practices for this situation? If not, are there any better ways to handle this from what I've mentioned?
EDIT Eric Lippert taught me this type of dispatch in one of his epic stackoverflow answers, and I'm searching for it at the moment. I will update this answer with a link if/when I track it down (the man has answered quite a few questions). Also, OP, you asked about performance, take a gander at this info also from Lippert: How does having a dynamic variable affect performance?
I would use a mix of dynamic with special case handling, and a generic type catch all for undefined (not yet implemented) types.
class Foo
{
public dynamic Value { get; set; }
}
class FooHandler
{
public void Serialize(Foo foo)
{
SerializeField(foo.Value);
}
void SerializeField(int field)
{
Console.WriteLine("handle int");
}
void SerializeField<T>(T field)
{
throw new NotImplementedException("Serialization not implemented for type: " + typeof(T));
}
}
class Program
{
[STAThread]
static void Main(string[] args)
{
Foo f = new Foo();
f.Value = 1;
FooHandler handler = new FooHandler();
handler.Serialize(f);
Console.ReadKey();
}
}
And then add types at your leisure.
You could use a dedicated class as a "multiple type variable".
At instantiation time you can pass an int, double, long, etc. and when you need to get the stored value out you can use a separate call.
public class Foo
{
public class Value
{
object _value;
public Value(int value) { _value = value; }
public Value(double value) { _value = value; }
public Value(long value) { _value = value; }
// etc
public object GetValue() { return _value; }
}
public void TestCall()
{
Value myValue = new Value(123);
Debug.WriteLine(myValue.GetValue());
}
}
I'd like to use a certain operation for multiple variable types (both native and objects) so I'm using the generic return type as follows.
private Generic Field<Generic>(String field)
{
if (BagOfJunk.Properties.Contains(field))
return (Generic)BagOfJunk[field];
return default(Generic);
}
This works well (and BagOfJunk is just a property of this from which I'm pulling out Object typed values). Now, during run-time, when a field isn't contained in the bag, I get the default value to be null. Hence, in the code, I need to perform a check as follows.
NumericType protoNumber = Field<NumericType>("beep");
int number = protoNumber != null ? protoNumber.Value : -1;
DateType protoDate = Field<DateType>("boop");
DateTime date = protoDate != null ? protoDate.Value : null;
I'd like to make the code more compact, so I tried to design a method that does the above four lines in one swoop, for a generic type. The result is below but, of course, it doesn't compile, because the type GenericIn isn't specific enough to have a property Value.
private GenericOut Field<GenericIn, GenericOut>(String field)
{
GenericIn input = Field<GenericIn>(field);
if (input != null)
return (GenericOut)input.Value;
return default(GenericOut);
}
How can I ensure the computer that my GenericIn isn't general - by promising that whatever stuff I'll shove into it, it'll always have the property Value in it?
Edit
It should be emphasized that the type of Value needs to be generic ( equivalent to GenericOut). I noticed that I didn't stress that strongly enough. So the interface that can be used need to declare a property of general type like the following.
interface ObjectWithValue { public Generic Value { get; } }
You can use an interface and apply a where constraint on the type to implement that interface, like below:
interface IHasPropertyValue<TValue> {
TValue Value { get; }
}
class MyType {
public TValue Method<T, TValue>(T obj) where T : IHasPropertyValue<TValue> {
return obj.Value;
}
}
EDIT: Modified the code above to make it more specific to the comment asked below.
put that property in an interface (or a class) and use the generic constraint "where":
public interface IMyInterface
{
public object Value { get; set; }
}
public class C<T> where T:IMyInterface
To build upon the answers so far, you need to create an interface that will be implemented by your GenericIn that will both guarantee that it has a property Value and that the property is of type GenericOut.
interface IHasValue<TOut>
{
TOut Value { get; }
}
private TOut Field<TIn, TOut>(string field) where TIn : IHasValue<TOut>
{
var input = Field<TIn>(field);
return input == null ? default(TOut) : input.Value;
}
I'm returning values from an Entity object. Some of them are String typed and some are not. Right now, I did a quick solution as follows.
private String GetStringValue(Entity entity, String attribute, String substitute = "")
{
if(entity.Contains(attribute)
return entity[attribute] as String;
return substitute;
}
private String GetIntValue(Entity entity, String attribute, int substitute = 0)
{
if(entity.Contains(attribute)
return entity[attribute] as int;
return substitute;
}
Then I remembered that there's a syntax for generic typing (something like <TypeX>). My question is, however, if there's a point to start changing the existing code. I'll need to change the signature of the method in two places (return type and substitute type) but I fear that I'll need to do some complex coding inside the method as well.
On the other hand, I'd have a nice way to treat all the types possible (and I have a hunch we'll be working with more than strings and integers.
You will have to change the signature of the method in three places, because you also have to add the generic parameter:
private T GetValue<T>(Entity entity, String attribute, T substitute)
Within the method, there's no real need for any complex coding; replacing your current occurrences of string or int, respectively, with T, should suffice. (Note that the as operator can only be applied if you restrict T to reference types - which you probably don't want to do, because int is a value type).
Note that there are two issues with this method that you might consider drawbacks:
This generic method will support "all the types possible", but it will also support any types impossible (users are free to specify whatever type they like for T, and there is no way to restrict T while still supporting both string and int.
You cannot specify arbitrary default substitute values for each type. What you can do is declare a default value for substitute, namely default(T), but at least for string, that is not an empty string, but null.
You are right "something like" is the generic method. Check out generic methods there.
Next method looks good for your purpose.
private static T GetValue<T>(Entity entity, string attribute, T defaultValue)
{
if (!entity.Contains(attribute))
return defaultValue;
return (T)entity[attribute];
}
EDIT: updated according of the w0lf's comment.
If you don't want to change method signature, you can write a generic function and call it from all of these non generic versions.
private String GetStringValue(...){
return GetValue<String>(...);
}
By the way, you are looking for Generic methods
For e.g (from msdn)
static void Swap<T>(ref T lhs, ref T rhs)
{
T temp;
temp = lhs;
lhs = rhs;
rhs = temp;
}
...
Swap<int>(ref a, ref b);
or just
Swap(ref a, ref b); //type int is infered based on type of arguements and method signature
What class is Entity? Assuming it's a custom class, make it also generic, then this works:
private T Get<T>(Entity<T> entity, T attribute, T substitute = default(T))
{
if (entity.Contains(attribute))
return entity[attribute];
return substitute;
}
You can retrieve the value in this way:
var entity = new Entity<string>();
string val = Get<string>(entity, "attr", "subst");
You should define your Entity<T> class:
public class Entity<T>
{
// TODO: implement
public T this[string i] { get; set; }
// TODO: implement
internal bool Contains(string attribute)
{
return true;
}
// TODO: implement
// other properties and methods
}
And you may use a generic method:
private T GetStringValue<T>(Entity<T> entity, String attribute, T substitute = default(T))
{
if (entity.Contains(attribute))
return entity[attribute];
return substitute;
}
If it is possible to generalize the code inside a method I would absolutely recommend to use it in a generic way. It makes the class smaller, better readable and you just have to change one method if requirements change. Your method looks like it can be made generic easily.
private T GetIntValue<T>(Entity entity, String attribute, T substitute = default(T))
{
if(entity.Contains(attribute))
return (T)entity[attribute];
return substitute;
}
If there would be some more logic to execute you could also use a dictionary with functions for the different types:
private IDictionary<Type, Func<Entity, string, object>> actions;
private void InitActions()
{
actions = new Dictionary<Type, Func<Entity, string, object>>
{
{
typeof (string), (entity, attribute) =>
{
// this could be your custom code for string
return entity[attribute];
}
},
{
typeof (int), (entity, attribute) =>
{
// this could be your custom code for int
return entity[attribute];
}
}
};
}
private T GetIntValue<T>(Entity entity, String attribute, T substitute = default(T))
{
if (entity.Contains(attribute) && actions.ContainsKey(typeof (T)))
{
Func<Entity, string, object> action = actions[typeof (T)];
return (T)action(entity, attribute);
}
return substitute;
}
I have a project I am working that will involve creating one DLL that will be used across multiple other sites. Inside this DLL we need to reference about 10 Enums. The values of these Enums however will be different for each site the DLL is used on. For example:
MyBase.dll may have a class MyClass with an attribute of type MyEnum.
MyBase.dll is then referenced in MySite. MyStie will also reference MyEnums.dll which will contain the values for the MyEnum type.
Is there any way to accomplish this? While building MyBase.dll, I know what enums will exist in side of MyEnums.dll. The problem is I cannot build MyBase.dll without specifically referenceing the MyEnums.dll, which is not created until the MyBase.dll is used in a specific project.
I hope that makes sense and hope I can find an answer here.
Thanks.
Edit:
Thanks for all the comments. It will take a few reads to completely understand, but let me try to give a better example of what I am looking at here.
Lets say the following code is in my DLL that will be put into various projects. Status is an enum.
public Class MyClass
{
private Status _currentStatus;
public Status CurrentStatus
{
get
{
return _currentStatus;
}
}
public void ChangeStatus(Status newStatus)
{
_currentStatus = newStatus;
}
}
What I want to be able to do is the define the possible values for Status in the individual projects. So in this DLL, I will never reference what values might be in the Status enum, I just have to know that it exists.
I hope that is a bit more clear on what I am trying to do.
If you want each client to see different enum values (in a different assembly version), then using an enum is a bad solution - changes will break client code...
Using an enum might work (as long as the enum names and assembly name are the same and the assembly isn't signed) - you could just swap the assembly. However, if a value is used anywhere in the code that isn't there at the end you'll end up with an exception. Also, you may have the explicitly number the values, to make sure different subsets of the values won't end up with the same number for different values or different numbers for the same value.
Instead consider using a dynamically built collection, e.g. a list, a dictionary or a database table. Or just give the same assembly with the same superset of enum values to everyone and let the users decide which values are relevant to them (perhaps use significant prefixes for values as a convention).
Or you could use a combination of the two...
Generate a different structure (different type name (or namespace) and assembly name) per site with different properties (according to site's profile) and one master structure for the service that accepts the structures. Have all the structures implement the same interface, which you expect to receive...
public interface IStatus
{
string GetKey();
}
public struct ClientXStatus : IStatus
{
private readonly string _key;
private ClientXStatus(string key)
{
_key = key;
}
// Don't forget default for structs is 0,
// therefore all structs should have a "0" property.
public ClientXStatus Default
{
get
{
return new ClientXStatus();
}
}
public ClientXStatus OptionB
{
get
{
return new ClientXStatus(10);
}
}
string IStatus.GetKey()
{
return _key;
}
public override bool Equals(object obj)
{
return (obj is IStatus) && ((IStatus)obj).GetKey() == _key;
}
public override int GetHashCode()
{
return _key.GetHashCode();
}
public static bool operator==(ClientXStatus x, IStatus y)
{
return x.Equals(y);
}
public static bool operator==(IStatus x, ClientXStatus y)
{
return y.Equals(x);
}
public static bool operator!=(ClientXStatus x, IStatus y)
{
return !x.Equals(y);
}
public static bool operator!=(IStatus x, ClientXStatus y)
{
return !y.Equals(x);
}
// Override Equals(), GetHashCode() and operators ==, !=
// So clients can compare structures to each other (to interface)
}
Use a master struct for the service:
public struct MasterStatus : IStatus
{
private readonly string _key;
private MasterStatus(string key)
{
_key = key;
}
// Don't forget default for structs is 0,
// therefore all structs should have a "0" property.
public MasterStatus Default
{
get
{
return new MasterStatus();
}
}
// You should have all the options here
public MasterStatus OptionB
{
get
{
return new MasterStatus(10);
}
}
// Here use implicit interface implementation instead of explicit implementation
public string GetKey()
{
return _key;
}
public static implicit operator MasterStatus(IStatus value)
{
return new MasterStatus(value.GetKey());
}
public static implicit operator string(MasterStatus value)
{
return new value._key;
}
// Don't forget to implement Equals, GetHashCode,
// == and != like in the client structures
}
Demo service code:
public void ServiceMethod(IStatus status)
{
switch (status.GetKey())
{
case (string)MasterStructA.OptionB:
DoSomething();
}
}
Or:
public void ChangeStatus(IStatus status)
{
_status = (MasterStatus)status;
}
This way you:
Use code generation to prevent collision of values.
Force users to use compile time checks (no int values or string values) by hiding values (as private) and only accepting your structures.
Use real polymorphism in the service's code (an interface) and not a error-prone hack.
Use immutable value types (like enums) and not reference types.
First you have to decide WHERE to put your constants. Then you can transform your enum to static properties.
For example:
public enum MyEnum
{
Value1,
Value2
}
Can be changed to (first naive approach):
public static class MyFakeEnum
{
public static int Value1
{
get { return GetActualValue("Value1"); }
}
public static int Value2
{
get { return GetActualValue("Value2"); }
}
private static int GetActualValue(string name)
{
// Put here the code to read the actual value
// from your favorite source. It can be a database, a configuration
// file, the registry or whatever else. Consider to cache the result.
}
}
This simply will provide required constants but you'll have to throw away compile-time check for the type if you'll need MyFakeEnum as parameter. For a better solution you can follow, for example, what Microsoft did (more or less) for System.Drawing.Color.
public sealed class MyFakeEnum
{
public static readonly MyFakeEnum Value1 = new MyFakeEnum("Value1");
public static readonly MyFakeEnum Value2 = new MyFakeEnum("Value2");
private MyFakeEnum(string name)
{
_name = name;
}
public static implicit operator int(MyFakeEnum value)
{
return GetActualValue(value._name);
}
private string _name;
}
Of course you should provide proper overides at least for Equals, GetHashCode and ToString.
Pro
It can be an upgrade from an existing enum. Code won't be breaked and you may just need to recompile.
You can use it as strongly typed parameter. For example: void DoSomething(MyFakeEnum value) is valid and callers can't pass something else (note that this is one of the reasons because enums are considered weak).
If you implement all the required operators you can use the normal syntax for comparison: value == MyFakeEnum::Value1.
With a little bit of code you may even implement the FlagsAttribute syntax.
You do not change the normal syntax of enums: MyFakeEnum.Value1.
You can implement any number of implicit/explicit conversion operators to/from your type and any conversion will be safe and checked in the point it's done (this is not true again with standard enums).
You do not have hard-coded strings that can be breaked by changes and won't be catched until they cause a run-time error (yes, run-time). Using, for example, a dictionary if you'll change the definitions then you'll have to search all your code for that string.
Cons
First implementation is longer because you have to write support code (but for any new value you'll simply add a new line).
Value list is fixed and must be known at compile time (this is not an issue if you're searching a replacement for an enum because it's fixed too).
With this solution you may save more or less the same syntax you had with standard enums.
Is it possible to write in C# method in such a way that when I write
String contestId = getParameter("contestId")
i get contestId in string, but when I write:
int contestId = getParameter("contestId")
i get contestId parsed to integer?
This is only simple example showing what i try to achieve.
Nope it's not possible to overload methods solely based on their return type. You could, however, introduce a generic parameter:
T getParameter<T>(string input) {
// ... do stuff based on T ...
}
And if you were using C# 3.0 you could use this method as:
var str = getParameter<string>("contestid");
var integer = getParameter<int>("contestid");
thus saying the actual type only once.
One thing you could do is return a separate object, which has implicit conversion operators to both int and string. That would get fairly close to the behavior you're asking for.
I wouldn't do that in practice though. Implicit conversions generally cause more trouble than they're worth.
Instead, add a generic parameter, like Mehrdad showed:
var str = getParameter<string>("contestid");
var integer = getParameter<int>("contestid");
I prefer this approach, it reads nicely.
Public Class ResultProxy
{
Private Object _Obj
Public ResultProxy(Object O)
{ _Obj = O; }
Public T As<T>()
{ return (T)_Obj; }
}
...
Public ResultProxy getParameter("contestId")
{
// your method's code
return new ResultProxy(YourPersonalFavorateReturnType);
}
...
String s = getParameter("contestId").As<String>();
Firstly the answer is no as many people have mentioned. Why? Do you have to assign the result of a method to something? For example can you have
int getValue()
{
return 4;
}
getValue();
The answer is yes, it can, so there is no way for the compiler to know which method you intend to call by its return type.
Personal opinion here, but I would suggest something along the lines of
public string getContestIdAsString(string ConetestId);
public int getContestIdAsInt(string ContestId);
Very obvious what each one is doing and you get around your problem. Unless there is something that I am missing.
public T GetParameter<T>(string parameterName)
{
//Do work
return value
}
string contestId = getParameter<string>("contestId")
int contestId = getParameter<int>("contestId")
This is an example of your best bet.