snippetcsharpMinor
Dynamically convert property to different data type
Viewed 0 times
dynamicallyconverttypedifferentpropertydata
Problem
The code finds marked attributes and parses them according to the attribute type.
Is it possible to simplify this logic? Is there generic way to do it? Please suggest some way to optimise this code. All the data type of
If there is list of items it will throw error in XMl and we won't know which row has caused the error.
```
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace TestSolution
{
public interface ICustomParser
{
bool Parse(string input);
}
public class DecimalParserAttribute : Attribute, ICustomParser
{
public bool Parse(string input)
{
if (input == null) return false;
decimal decimalValue;
return decimal.TryParse(input, out decimalValue);
}
}
public class intParserAttribute : Attribute, ICustomParser
{
public bool Parse(string input)
{
if (input == null) return false;
int intValue;
return int.TryParse(input, out intValue);
}
}
public class Product
{
[DecimalParser]
public string Weight { get; set; }
[intParser]
public string NoOfItems { get; set; }
[intParser]
public string GRodes { get; set; }
[intParser]
public string WRodes { get; set; }
}
class Program
{
static void Main(string[] args)
{
var sb = Validate(new Product() { NoOfItems = "1", GRodes = "4", Weight = "5", WRodes = "23" });
Console.WriteLine(sb);
sb = Validate(new Product() { NoOfItems = "1", GRodes = "4w", Weight = "5", WRodes = "23" });
Console.WriteLine(sb);
Console.ReadKey();
}
Is it possible to simplify this logic? Is there generic way to do it? Please suggest some way to optimise this code. All the data type of
Product class will be string. I'm getting product input as XML directly converting serialized data to a class with decimal, int, float will not give proper error message.If there is list of items it will throw error in XMl and we won't know which row has caused the error.
```
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace TestSolution
{
public interface ICustomParser
{
bool Parse(string input);
}
public class DecimalParserAttribute : Attribute, ICustomParser
{
public bool Parse(string input)
{
if (input == null) return false;
decimal decimalValue;
return decimal.TryParse(input, out decimalValue);
}
}
public class intParserAttribute : Attribute, ICustomParser
{
public bool Parse(string input)
{
if (input == null) return false;
int intValue;
return int.TryParse(input, out intValue);
}
}
public class Product
{
[DecimalParser]
public string Weight { get; set; }
[intParser]
public string NoOfItems { get; set; }
[intParser]
public string GRodes { get; set; }
[intParser]
public string WRodes { get; set; }
}
class Program
{
static void Main(string[] args)
{
var sb = Validate(new Product() { NoOfItems = "1", GRodes = "4", Weight = "5", WRodes = "23" });
Console.WriteLine(sb);
sb = Validate(new Product() { NoOfItems = "1", GRodes = "4w", Weight = "5", WRodes = "23" });
Console.WriteLine(sb);
Console.ReadKey();
}
Solution
I think you kind of reinventing the wheel a bit here. You could use the ValidationAttribute.
Since C# doesn't allow generics in Attribute classes you either have to create an attribute per type or use an enum to specific what type. I personally prefer an attribute per type.
An Example of use the ValidationAttrubte for DecimalParser
Now to perform the validation you need to use the Validator Class
This to me fits more in with what you are doing, validation, with the benefit of using the built in .Net Framework classes.
Since C# doesn't allow generics in Attribute classes you either have to create an attribute per type or use an enum to specific what type. I personally prefer an attribute per type.
An Example of use the ValidationAttrubte for DecimalParser
public class DecimalParserAttribute : ValidationAttribute
{
public DecimalParserAttribute() : base("Cannot convert to decimal")
{
}
public override bool IsValid(object value)
{
if (value == null)
{
return false;
}
var stringValue = Convert.ToString(value);
decimal decimalResult;
return decimal.TryParse(stringValue, out decimalResult);
}
}Now to perform the validation you need to use the Validator Class
var p = new Product() {NoOfItems = "1", GRodes = "4w", Weight = "5", WRodes = "2q3"};
var validationResults = new Collection();
if (!Validator.TryValidateObject(p, new ValidationContext(p), validationResults, true))
{
// If we are here there was validation errors
var x = string.Join(Environment.NewLine,
validationResults.SelectMany(r => r.MemberNames.Select(n => n + " " + r.ErrorMessage)));
}This to me fits more in with what you are doing, validation, with the benefit of using the built in .Net Framework classes.
Code Snippets
public class DecimalParserAttribute : ValidationAttribute
{
public DecimalParserAttribute() : base("Cannot convert to decimal")
{
}
public override bool IsValid(object value)
{
if (value == null)
{
return false;
}
var stringValue = Convert.ToString(value);
decimal decimalResult;
return decimal.TryParse(stringValue, out decimalResult);
}
}var p = new Product() {NoOfItems = "1", GRodes = "4w", Weight = "5", WRodes = "2q3"};
var validationResults = new Collection<ValidationResult>();
if (!Validator.TryValidateObject(p, new ValidationContext(p), validationResults, true))
{
// If we are here there was validation errors
var x = string.Join(Environment.NewLine,
validationResults.SelectMany(r => r.MemberNames.Select(n => n + " " + r.ErrorMessage)));
}Context
StackExchange Code Review Q#150278, answer score: 4
Revisions (0)
No revisions yet.