Passing parameters with conditionally - c#

Update:
I have a dropdownlist with seven different options like (date, subject, press, cia, media...) and user will select one of the item from the dropdownlist and click on search button to get the results.
Here is my repository class GetInquiries method which accepts 7 parameters but it will pass only one parameters at a time to the stored procedure and in case of Date (it will pass both from/to)
public List<Inquiry> GetInquiries(string fromDate, string toDate,
string subject, string press,
string cia, string media,
string status)
Here is what I have come up with passing the parameters to GetInquiries:
if (!string.IsNullOrEmpty(this.txtSubject.Text.Trim()))
{
e.Result = reporterRepo.GetInquiries(null,null,txtSubject.Text,null,null,null,null);
}
else
{
e.Result = reporterRepo.GetInquiries(null,null,null,null,null,null,null);
}
else if (!string.IsNullOrEmpty(this.fromDate.Text.Trim()))
e.Result = reporterRepo.GetInquiries(fromDate.Text,null,null,null,null,null,null)
.......................
...................
....................
I have to continue seven times with (if else if conditions) for all seven parameters.
Is there a way I can do it more clearly and more readability?

Well, depending on your exact situation, this might help:
e.Result = reporterRepo.GetInquiries(null, null,
string.IsNullOrEmpty(this.txtSubject.Text.Trim()) ? null : txtSubject.Text,
null, null, null, null);
Or if you're using C# 4 and can modify GetInquiries, you could possibly make all the parameters optional and use named arguments to specify which one you're actually providing.
Or write methods such as GetInquiriesByName, GetInquiriesBySubject etc to avoid overloading with clashing parameter types.
EDIT: If there's a dropdown, it sounds like you should be using the value of that to determine the appropriate branch to take (i.e. what to search on) and then go from there.

If you are using .NET 4.0 then you take advantge of optional and default parameters. If you're using an earlier framework version, then try creating overloasd of the routine:
public List<Inquiry> GetInquiries(string fromDate, string toDate,
string subject, string press,
string cia, string media)
{
// Pass empty string for status.
return this.GetInquiries(fromDate, toDate, subject, press, cia, media, String.Empty)
}
public List<Inquiry> GetInquiries(string fromDate, string toDate,
string subject, string press,
string cia, string media,
string status)

var subjectText = this.txtSubject.Text.Trim();
var dateText = this.fromDate.Text.Trim();
if (subjectText.Length == 0) subjectText = null;
if (dateText .Length == 0) dateText = null;
e.Result = reporterRepo.GetInquiries(dateText ,null,subjectText,
null,null,null,null);
string.IsNullOrEmpty(this.txtSubject.Text.Trim()))
Note that this.txtSubject.Text.Trim() will never be null, and if this.txtSubject.Text is null, this will throw an exception.

You reflection to invoke the method GetInquiries with just the n-th argument set.
public List<Inquiry> GetInquiries(int numparam, string myparameter)
{
object[] params = new object[7];
params[numparam] = myparameter;
reporterRepo.Gettype().GetMethod("GetInquiries").Invoke(reporterRepo, params);
}
I have not tested the code but you get the idea.

public class Inquiries
{
private SqlParameter[] _parameters;
public DateTime FromDate { get{ //return value from parameters array} set{ // add a new parameter to your array } }
public DateTime ToDate { get{ //return value from parameters array} set{ // add a new parameter to your array } }
public String Subject { get{ //return value from parameters array} set{ // add a new parameter to your array } }
public String Press { get{ //return value from parameters array} set{ // add a new parameter to your array } }
public String Cia { get{ //return value from parameters array} set{ // add a new parameter to your array } }
public String Media { get{ //return value from parameters array} set{ // add a new parameter to your array } }
public List<Inquiry> Get()
{
// Your dal code using the parameters array
}
}
Then make Inquiries a member level in the formthat's going to get inquiries, and with the changes you do, set the properties appropriately, unless you're only going to do one property at a time then just create the class and toss it each time you use it as:
List<Inquiry> myInquires = new Inquiry() { Subject = txtSubject.Text }.Get();

What about using some sort of a specification pattern
So in your example the usage would be
var querySpecification = new QuerySpecification();
if (!string.IsNullOrEmpty(this.txtSubject.Text.Trim()))
{
querySpecification = new WhereSubject().Is(txtSubject);
}
else if (!string.IsNullOrEmpty(this.fromDate.Text.Trim()))
{
querySpecification = new WhereFromDate().Is(fromDate);
}
else
{
querySpecification = new All();
}
e.Result = reporterRepo.GetInquiries(querySpecification);
WhereSubject, WhereFromDate and All derives from a common IReportReposSpec.
public interface IReportReposSpec
{
void Is(object value)
// stored proc translation of the spec
string Param {get;}
string DbType {get;}
string Value {get;}
}
The implementation of reporterRepo.GetInquiries could be as such
public List<Inquiry> GetInquiries(IReportReposSpec spec)
{
var cmd = new SqlCommand();
cmd.CommandType = CommandType.StoredProcedure;
// for simplicity i'm going to use a pseudo code from here on
cmd.AddParam(spec.Param, spec.DbType, spec.Value));
//...
}

Related

how can i convert a null value from sql to datetime or string in C#?

I am trying to get some datetime values that are null in SQL to my C# application but i get some errors. One of the errors is:
'Unable to cast object of type 'System.DBNull' to type 'System.String'
Please, can someone tell me how to set a null DateTime value from SQL to my c# application?
I have already tried casting my C# variables to datetime value and string but both dont work. I've searched in stackoverflow but didn't found a solution for me.
I've also tried another solution but then i retrieved the date: '01/01/0001' as value instead of 'null'
public static List<Kamer> GetOpenstaandeBoekingen()
{
var result = new List<Kamer>();
using (var conn = new SqlConnection(ConnectionString))
{
conn.Open();
const string query = "select b.boekingid, k.naam, bk.incheckdatum, bk.uitcheckdatum, b.hotelid, b.aantal_gasten, bk.kamerid from boeking b join klant k on k.klantid = b.boekingid join boekingkamer bk on b.boekingid = bk.boekingid where bk.incheckdatum is null and bk.uitcheckdatum is null";
SqlCommand selectKamers = new SqlCommand(query, conn);
SqlDataReader reader = selectKamers.ExecuteReader();
while (reader.Read())
{
Kamer kamer = new Kamer((int)reader["boekingid"], (string)reader["naam"], (string)reader["incheckdatum"], (string)reader["uitcheckdatum"], (int)reader["hotelid"], (int)reader["aantal_gasten"], (int)reader["kamerid"]);
result.Add(kamer);
}
reader.Close();
}
return result;
}
And here is my class with the constructor:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FontysHotel
{
public class Kamer
{
// instantie variabelen
private int id;
private string naam;
private DateTime incheck_datum;
private DateTime uitcheck_datum;
private int hotel;
private int aantal_personen;
private int kamernr;
// properties
public int Id
{
get
{
return id;
}
set
{
id = value;
}
}
public string Naam
{
get
{
return naam;
}
set
{
naam = value;
}
}
public string Incheck_datum
{
get
{
return incheck_datum.ToShortDateString();
}
set
{
incheck_datum = Convert.ToDateTime(value);
}
}
public string Uitcheck_datum
{
get
{
return uitcheck_datum.ToShortDateString();
}
set
{
uitcheck_datum = Convert.ToDateTime(value);
}
}
public int Hotel
{
get
{
return hotel;
}
set
{
hotel = value;
}
}
public int Aantal_personen
{
get
{
return aantal_personen;
}
set
{
aantal_personen = value;
}
}
public int Kamernr
{
get
{
return kamernr;
}
set
{
kamernr = value;
}
}
public Kamer(int id, string naam, string incheck_datum, string uitcheck_datum, int hotel, int aantal_personen, int kamernr)
{
Id = id;
Naam = naam;
Incheck_datum = incheck_datum;
Uitcheck_datum = uitcheck_datum;
Hotel = hotel;
Aantal_personen = aantal_personen;
Kamernr = kamernr;
}
}
}
Uitcheckdatum and incheckdatum are the date values.
So i want, when i run the query is shows everything where are dates with null, it is for a hotel system and i want to show what bookings haven't checked in or out yet.
One way is to declare your DateTime variables as being a Nullable type, this is done by using the ? sign at the end such as this.
private DateTime? incheck_datum;
private DateTime? uitcheck_datum;
But it might be a better approach to look for, trap, and handle DB Nulls and then set default or min values like this
if (IsDBNullreader.IsDBNull(indexOfUitCheckDatum))
uitcheckdatum = DateTime.Minvalue;
else
uitcheckdatum = reader["uitcheckdatum"];
I would avoid direct initialization of an object without any previous check.
If you want to treat a DBNull value from the database as a null DateTime, there's no other option than declaring your two fields in the Kamer class using the nullable version DateTime? instead, since DateTime alone is a struct, a value type, which cannot be null. With that, you could do:
set
{
uitcheck_datum = string.IsNullOrEmpty(value) ? null : Convert.ToDateTime(value);
}
And in the loop:
while (reader.Read())
{
string incheckdatum = reader["incheckdatum"] as string;
string uitcheckdatum = reader["uitcheckdatum"] as string;
Kamer kamer = new Kamer((int)reader["boekingid"], (string)reader["naam"],
incheckdatum, uitcheckdatum, (int)reader["hotelid"],
(int)reader["aantal_gasten"], (int)reader["kamerid"]);
result.Add(kamer);
}
as saves you from possible casting exceptions. The indexer returns an instance of object. If it can't be cast to string, then null is returned.
In case you don't want to declare those fields as DateTime?, then just replace null in the set with a dummy date of your choice, e.g. DateTime.Now.
Also, make sure the string you receive from the database is a convertable string, or Convert will throw an exception. Maybe you'd want to add a try-catch to handle it.

C#: How to set default value if input is empty

If I have a method like this:
public void AddSomething(string ice = "10", string sweet = "20")
{
Console.Write(ice);
Console.Write(sweet);
}
so if I input a string, it will write the string. If not, it will write the default string(10,20).
But I want something like this:
public void AddSomething(string ice = "10", string sweet = "20")
{
if(ice = "")
ice = default_vaule; //which is 10
if(sweet = "")
sweet = default_vaule; //which is 20
Console.Write(ice);
Console.Write(sweet);
}
so if user input a empty string "", I can write the default value to user, so I can do not only this:
AddSomething("5");
Also both of these:
AddSomething("5","");
AddSomething("","5");
Anyone knows how to do that? THX!
you already answered your question. you can cover null cases also.
public void AddSomething(string ice = "10", string sweet = "20")
{
if(string.IsNullOrEmpty(ice)) ice = "10";
if(string.IsNullOrEmpty(sweet)) sweet = "20";
Console.Write(ice);
Console.Write(sweet);
}
you can use constants if you don't want to write duplicate literals.
// these are constant and can be used as default value for parameters.
const string DefaultSweet = "20";
const string DefaultIce = "10";
public void AddSomething(string ice = DefaultSweet, string sweet = DefaultIce)
{
if(string.IsNullOrEmpty(ice)) ice = DefaultIce;
if(string.IsNullOrEmpty(sweet)) sweet = DefaultSweet;
Console.Write(ice);
Console.Write(sweet);
}
side note: string.IsNullOrEmpty(ice) is equivalent to ice == "" || ice == null
So you want to get the default value of a method-parameter at runtime without repeating yourself, so without typing that value again(f.e. to prevent that have you change it there too if you change the default value of the parameter)?
That's not easy because there is no defaultof(parameter)-operator (similar to the nameof-operator). You had to use reflection.
You could use this extension:
public static class MethodExtensions
{
public static Result<T> ParameterDefault<T>(this MethodBase m, string paramName)
{
ParameterInfo parameter = m.GetParameters()
.FirstOrDefault(p => p.Name == paramName);
if (parameter == null)
throw new ArgumentException($"No parameter with given name '{paramName}' found", nameof(paramName));
if (parameter.ParameterType != typeof(T))
throw new ArgumentException($"Parametertype is not '{typeof(T)}' but '{parameter.ParameterType}'");
if(parameter.HasDefaultValue)
return new Result<T>((T)parameter.DefaultValue, true);
else
return new Result<T>(default(T), false);
}
}
which returns an instance of following class, which is just a wrapper to enable to also return the information if the default value could be determined:
public class Result<T>
{
public Result(T value, bool success)
{
Value = value;
Success = success;
}
public T Value { get; private set; }
public bool Success { get; private set; }
}
Now your method looks like:
public void AddSomething(string ice = "10", string sweet = "20")
{
MethodBase m = MethodBase.GetCurrentMethod();
if (ice == "")
ice = m.ParameterDefault<string>(nameof(ice)).Value;
if (sweet == "")
sweet = m.ParameterDefault<string>(nameof(sweet)).Value;
Console.Write(ice);
Console.Write(sweet);
}
and you don't need to repeat the parameter value.
This question ( at least for me ) is unclear but from what you've posted I can suggest solution like this :
// default value for "ice"
const string default_ice = "10";
// default value for "sweet"
const string default_sweet = "20";
public void AddSomething(string ice = default_ice, string sweet = default_sweet)
{
// check if "ice" value is set
if(string.IsNullOrEmpty(ice))
ice = default_ice; // set "ice" value to the default one
// check if "sweet" value is set
if(string.IsNullOrEmpty(sweet))
sweet = default_sweet; // set "sweet" value to the default one
Console.Write(ice);
Console.Write(sweet);
}
You can then also call it like such:
AddSomething(sweet: "1337");
// or
AddSomething("13", "37");
or however you like.
Try this online

Same Remote Validation for 2 different properties in a model

I have 2 properties contractor1 and contractor2 in a model, how can I use a single remote validation for both of them
[Display(Name ="Contractor 1:")]
[Remote("ValidateContractor", "Contracts")]
public string Cntrctr1 {get; set;}
[Display(Name = "Contractor 2:")]
[Remote("ValidateContractor", "Contracts")]`enter code here`
public string Cntrctr2 {get; set;}
Remote Validation function in the Controller
public JsonResult ValidateContractor1(string Cntrctr)
{
var valid = Validations.ValidateContractor(Cntrctr);
if (!valid)
{return Json("Enter correct contractor", JsonRequestBehavior.AllowGet);}
else{return Json(true, JsonRequestBehavior.AllowGet);}
}
public static bool ValidateContractor(string CntrctrNM)
{
bool valid;
using (var entities = new CAATS_Entities())
{
var result = (from t in entities.PS_VENDOR_V
where (t.VNDR_1_NM).Equals(CntrctrNM)
select t).FirstOrDefault();
if (result != null)
{
valid = true;
}
else
{
valid = false;
}
}
return valid;
}
This doesn't work. Can you please help me with this?
When remote validation is called, the querystring key is the name of the field, e.g. in your case /Contracts/ValidateContractor1?Cntrctr1=foo. You need a more dynamic solution.
One way you can do this is to not have any parameters in ValidateContractor1 and just grab the first query string value instead. This isn't tested but should work for you:
public JsonResult ValidateContractor1()
{
// gets the name of the property being validated, e.g. "Cntrctr1"
string fieldName = Request.QueryString.Keys[0];
// gets the value to validate
string Cntrctr = Request.QueryString[fieldName];
// carry on as before
var valid = Validations.ValidateContractor(Cntrctr);
if (!valid)
{return Json("Enter correct contractor", JsonRequestBehavior.AllowGet);}
else{return Json(true, JsonRequestBehavior.AllowGet);}
}
Adding onto Rhumborls answer if you find his method not to work it might be because you're using forms; if this is the case you need to use the Form attribute instead of the QueryString as so.
public JsonResult ValidateContractor()
{
// gets the name of the property being validated, e.g. "Cntrctr1"
string fieldName = Request.Form.Keys[0];
// gets the value to validate
string Cntrctr = Request.Form[fieldName];
// carry on as before
var valid = Validations.ValidateContractor(Cntrctr);
if (!valid)
{return Json("Enter correct contractor", JsonRequestBehavior.AllowGet);}
else{return Json(true, JsonRequestBehavior.AllowGet);}
}

How to string a value across two functions?

I am new to the world of c# so go easy on me! :]
I am not even sure I am using the correct terminology. I figured this would be an easy google search but I am afraid I may not be wording this correctly.
I am gathering data from a database. Like so:
SqlConnection mySqlConnection = new SqlConnection(strings.settings.connectionString);
SqlCommand mySqlCommand = mySqlConnection.CreateCommand();
mySqlCommand.CommandText = "SELECT FNAME, LNAME, ZIPCODE FROM database WHERE ID = #ID";
mySqlCommand.Parameters.Add("#ID", SqlDbType.Char).Value = txtID.Text;
mySqlConnection.Open();
SqlDataReader mySqlDataReader = mySqlCommand.ExecuteReader(CommandBehavior.SingleRow);
if (mySqlDataReader.HasRows == false)
{
throw new Exception();
}
if (mySqlDataReader.Read())
{
txtFname.Text = mySqlDataReader[0].ToString();
txtLname.Text = mySqlDataReader[1].ToString();
lblZipcode.Text = mySqlDataReader[2].ToString();
//need help on stringing the value ZIPCODE above.
}
My question is: How can I string the Zipcode value to another function? I have been trying things like
string Zipcode = mySqlDataReader[2].ToString();
but I get stuck trying to figure out how to string that value so I can use it in a different function like so:
private void GetZipData()
{
//Get that value
}
Any help or a point in the right direction would be greatly appreciated!
Either I've misunderstood the question or your approach is fundamentally wrong. Firstly, your GetZipData() is returning void so is a subroutine, not a function. Even better, refer to it as a method as that covers both subs and funcs...
You can pass parameters in like this...
public void GetZipData(String SomeInputString) {
///Do something
}
and you can return things from a function like this...
public String GetZipData() {
return "Some String";
}
What I suspect you want to do is get either a single Zip code or a list of zip codes from a data reader. Something like...
public String GetZipData(Integer Id) {
//All your MySQL Code here
return mySqlDataReader[2].ToString();
}
then you can simply call it like this...
String TheZipCode = GetZipData(123);
Of course, there are other things you can consider doing too - like creating a class to represent a customer and return that instead of a string - then you can get all the information in one Db trip...
class Person {
String Firstname;
String Lastname;
String ZipCode;
}
public Person GetPersonData(Integer Id) {
//All your MySQL Code here
Person ReturnData = new Person();
ReturnData.Firstname = mySqlDataReader[0].ToString();
ReturnData.Lastname = mySqlDataReader[1].ToString();
ReturnData.ZipCode = mySqlDataReader[2].ToString();
return ReturnData;
}
Then you'd have...
Person person = GetPersonData(12);
//You can now use person.Firstname, person.ZipCode, etc...
Change this method as
private string GetZipData()
{
string Zipcode = mySqlDataReader[2] as String;
return Zipcode;
}
I am not sure what you are trying to achieve. If you want to pass the zip string to antoher method, you can add a string parameter to that method
private void DoSomethingWithZipCode(string zipCode)
{
Console.WriteLine(zipCode);
}
If you want to return antoher value that depends on the zip code, you need a return type as well
private string GetCity(string zipCode)
{
string city = <get city from database>;
return city;
}
Or in your case
private string GetZipData(SqlDataReader dataReader)
{
return dataReader[2].ToString();
}
You would call it like this
lblZipcode.Text = GetZipData(mySqlDataReader);
You can also write an extension method. You must place this method in a static class whose namespace is available where you are using it
public static string ZipData(this SqlDataReader dataReader)
{
return dataReader[2].ToString();
}
You can call it like this
lblZipcode.Text = mySqlDataReader.ZipData();
string Zipcode = mySqlDataReader[2].ToString();
private void GetZipData(string yourInput)
{
//do your stuff with yourInput
}
If your top data access code is in its own method you can 'return' it from there you would then call your data access method from the new value, see below:
return ZipCode
private void GetZipData() {
var stry=DataCode();
}
Regards
Craig

Is there a good C# design pattern for parsing strings that when split have different amounts of data?

I am dealing with values delimited by commas sent to me as a string. The strings come in many different structures (meaning different data types in different locations of the string as well as varying amounts of data). So while one string might be represented as:
- common data,identifier,int,string,string,string.
Another might be represented as:
- common data,identifier,int,int,string,string,string.
Design goals:
Common parse method
Common validation (i.e. int.TryParse() returns true)
Readily able to add different structures
Is there a good design pattern, or combination of design patterns, that allows me to parse the values, check them, and return an object only if the right amount of values were pulled in and those values were the expected data types?
Note: I am dealing with more than 30 different string structures.
If all the lines start with common data, identifier, and then are followed by a variable but expected (i.e. known based on the identifier) set of values, then a table approach could work well. To continue your example, say you have two different types:
common data,identifier,int,string,string,string.
common data,identifier,int,int,string,string,string.
You can build a class that defines what you're looking for:
class ItemDesc
{
public string Ident { get; private set; }
public string Fields { get; private set; }
public ItemDesc(string id, string flds)
{
Ident = id;
Fields = flds;
}
}
The Fields property is just a string that contains one-character type descriptions for the variable data. That is, "isss" would be interpreted as int,string,string,string.
You can then build a Dictionary<string, ItemDesc> that you can use to look these up:
Dictionary<string, ItemDesc> ItemLookup = new Dictionary<string, ItemDesc>
{
{ "ItemType1", new ItemDesc("ItemType1", "isss") },
{ "ItemType2", new ItemDesc("ItemType2", "iisss") },
};
Now when you read a line, use string.Split() to split it into fields. Get the identifier, look it up the dictionary to get the item descriptions, and then parse the rest of the fields. Something like:
string line = GetLine();
var fields = line.Split(',');
// somehow get the identifier
string id = GetIdentifier();
ItemDesc desc;
if (!ItemLookup.TryGetValue(id, out desc))
{
// unrecognized identifier
}
else
{
int fieldNo = 3; // or whatever field is after the identifier
foreach (var c in desc.Fields)
{
switch (c)
{
case 'i' :
// try to parse an int and save it.
break;
case 's' :
// save the string
break;
default:
// error, unknown field type
break;
}
++fieldNo;
}
}
// at this point if no errors occurred, then you have a collection
// of parsed fields that you saved. You can now create your object.
would need little more details, based on your problem domain it could entirely change. but following seem to be the first set of patterns, they are ordered on suitability.
Interpreter
Strategy
Builder
Just split them using string.Split(), and then int.Parse() or int.TryParse() each int value in the resulting array as needed.
var myStrings = string.Split(sourceString);
int myint1 = int.Parse(myStrings[0]);
There are several ways of dealing with this. Here's a simple one (outputting just an object array):
class Template
{
// map identifiers to templates
static Dictionary<string, string> templates = new Dictionary<string, string>
{
{ "type1", "isss" },
{ "type2", "iisss" },
};
static bool ParseItem(string input, char type, out object output)
{
output = null;
switch (type)
{
case 'i':
int i;
bool valid = int.TryParse(input, out i);
output = i;
return valid;
case 's':
output = input;
return true;
}
return false;
}
public static object[] ParseString(string input)
{
string[] items = input.Split(',');
// make sure we have enough items
if (items.Length < 2)
return null;
object[] output = new object[items.Length - 2];
string identifier = items[1];
string template;
// make sure a valid identifier was specified
if (!templates.TryGetValue(identifier, out template))
return null;
// make sure we have the right amount of data
if (template.Length != output.Length)
return null;
// parse each item
for (int i = 0; i < template.Length; i++)
if (!ParseItem(items[i + 2], template[i], out output[i]))
return null;
return output;
}
}
If you're interested in returning actual objects instead of just object arrays, you can put metadata into the class definitions of the objects you're returning. Then when you get the object type you look for the metadata to figure out where to find its value in the input array. Here's a quick example:
namespace Parser
{
// create metadata attribute
class CsvPositionAttribute : Attribute
{
public int Position { get; set; }
public CsvPositionAttribute(int position)
{
Position = position;
}
}
// define some classes that use our metadata
public class type1
{
[CsvPosition(0)]
public int int1;
[CsvPosition(1)]
public string str1;
[CsvPosition(2)]
public string str2;
[CsvPosition(3)]
public string str3;
}
public class type2
{
[CsvPosition(0)]
public int int1;
[CsvPosition(1)]
public int int2;
[CsvPosition(2)]
public string str1;
[CsvPosition(3)]
public string str2;
[CsvPosition(4)]
public string str3;
}
public class CsvParser
{
public static object ParseString(string input)
{
string[] items = input.Split(',');
// make sure we have enough items
if (items.Length < 2)
return null;
string identifier = items[1];
// assume that our identifiers refer to a type in our namespace
Type type = Type.GetType("Parser." + identifier, false);
if (type == null)
return null;
object output = Activator.CreateInstance(type);
// iterate over fields in the type -- you may want to use properties
foreach (var field in type.GetFields())
// find the members that have our position attribute
foreach (CsvPositionAttribute attr in
field.GetCustomAttributes(typeof(CsvPositionAttribute),
false))
// if the item exists, convert it to the type of the field
if (attr.Position + 2 >= items.Length)
return null;
else
// ChangeType may throw exceptions on failure;
// catch them and return an error
try { field.SetValue(output,
Convert.ChangeType(items[attr.Position + 2],
field.FieldType));
} catch { return null; }
return output;
}
}
}

Categories