I'm trying to read a fixed length file and convert it to a delimited file format for use in Excel. Using the FileHelpers library I'm able to read/write either of these formats, but I'm having trouble converting between them.
My closest approach is to declare an abstract class for the record where I declare the fields in, specify the order and use any Converters. Then from that abstract class, derive a class for the delimited record and the fixed length record. I manage to get this to work up until I try to create the fixed length engine, at which point I get an exception that apparently some of the attributes aren't taking.
Here's what I have so far:
void Main()
{
// Arrange
var delimitedEngine = new FileHelperEngine<CustomerDelimitedRecord>();
var fixedLengthEngine = new FileHelperEngine<CustomerFixedLengthRecord>();
var input = #"C:\input.csv";
var output = #"C:\output.csv";
// Act
var records = (CustomerRecord[]) delimitedEngine.ReadFile(input);
fixedLengthEngine.WriteFile(output, (CustomerFixedLengthRecord[])records);
}
// Define other methods and classes here
public abstract class CustomerRecord
{
[FieldOrder(2)]
public string Name;
[FieldOrder(1)]
public int ID;
}
[DelimitedRecord(",")]
public class CustomerDelimitedRecord : CustomerRecord
{
}
[FixedLengthRecord]
public class CustomerFixedLengthRecord : CustomerRecord
{
[FieldFixedLength(50)]
public new string Name;
[FieldFixedLength(5)]
public new int ID;
}
This seems to not have any errors, but I get the following runtime exception:
Bad Usage Exception
The field: 'Name' must be marked the FieldFixedLength attribute
because the record class is marked with FixedLengthRecord.
I'm not sure if I'm on the right track, but I'm open to any suggestions. I feel this still wouldn't be the best solution, since I have to write the fields twice for the fixed length record class, but at least I don't have to write some of the attributes twice and save myself some mapping code.
By the way, I should be using at least autoproperties, but the limitations of FileHelpers means I can't because I need to use Custom Converters.
Related
I'm trying to find a way to define a class such that it has the same properties as another class, but with different property types (all strings), without having to enumerate the properties, and such that you can reference the properties via code rather than by a string key.
For clarification, below is an example of the functionality of what I am looking for...
public class ValuedClass
{
public int Value {get; set;}
}
public class StringedClass : Stringified<ValuedClass> {}
public class Program
{
public static void Main(int[] args)
{
var valued = new ValuedClass() { Value = 5 };
var stringed = new StringedClass() { Value = "taco" };
}
}
I've messed around with abstract classes w/ type arguments for each data type (ie. TNumber, TMoney, TDate, etc.), a Stingified with this[string propName] defined, making everything object types, and other solutions, but each one requires enumerating the properties again (thus giving another update failure point), or adds an unacceptable level of complexity to the code.
At this point, I'd think that I'd have to hijack how .net handles the code when you type valued.Value, and tell it to then go to this["Value"], but I haven't been able to find any way to do something like that either.
I have run into the following problem when trying to implement a simple spreadsheet program in C#.
What I am trying to do is to have a Table class which basically is an array of objects of class Cell. However I would like to implement a separate Parser class which would accept all user input. Yet the methods of the Parser class need to have access to table's cells. And I am not sure how that should be implemented.
Perhaps better explained by code:
class Cell
{
//fields
}
class Table
{
private Cell[,] cells;
public Cell At(int key);
}
static class Parser
{
public static Cell GetCellReference(string userInput)
{
//somehow
//return Table.At(parsedUserInput)
}
}
One way I see of achieving that is by instantiating a Table object inside Parser, but that clearly defeats the purpose of the parser class itself. Another way I see is by passing a Table object to Parser's methods, but that doesn't seem reasonable as the intent is to work with only one Table instance. Inheritance does not seem to apply between the parser and the table and so I find myself stuck. How should I change/modify the design to achieve the goal without violating basic principles of OOP?
I would have
public class Parser
{
public Parser(Table table){..}
public ReturnType DoIt(....) {...}
}
and then
var parser = new Parser(myTable);
var res = parser.DoIt(widgetWoo, bar33);
if you want PArser to be static then do
public static class Parser
{
public ReturnType Parse(Table table,.....){..}
}
and then
var res = Parser.Parse(myTable, widgetWoo, bar33);
However it feels to me that Parser will have a lot of internal state. Better to be non-static
Say I have a custom data class. It just holds data in a meaningful way.
The class might look like:
class MyClass
{
public struct MyType
{
public string parameter;
public string data;
public string value;
}
public List<MyType> myTypeList= new List<MyType>();
}
Say I have a program that creates many of these classes. The data is filled from parsing a number of files and the List<MyType> will have an indefinite number of items when done grabbing data. I then use this data in several ways throughout the program (Create documents, display on GUI, etc...).
When I add to the list in my Parsing class, I must first create a new object of MyType and then add it to myTypeList. So the parsing class has to actually know of and use the inner object type. Once it is added, though, I can just use an instance of MyClass to access the fields directly without any knowledge of type.
Such as:
string myString = myClassInstance.myTypeList[0].parameter;
Is it better to create a method inside the MyClass that lets the parsing class pass in data without knowledge of the underlying type? If so, what is the best way of doing this?
I can think of several ways to do it, I just don't know if it's the best or correct way. I guess it would better generalize the code, but could be less readable when adding data.
Edit: Adding in usage differences due to comment.
class MyParser
{
public List<MyClass> ParseFile(string[] lines)
{
List<MyClass> myClassInstance = new MyClass();
foreach(string line in lines)
{
MyType typeInstance = new MyType();
typeInstance.parameter = line.Substring(0, 1);
typeInstance.data = line.Substring(1, 1);
typeInstance.value = line.Substring(2, 1);
myClassInstance.myTypeList.Add(typeInstance);
}
}
}
Vs. Something like:
class MyParser
{
public List<MyClass> ParseFile(string[] lines)
{
List<MyClass> myClassInstance = new MyClass();
foreach(string line in lines)
{
myClassInstance.AddData(line.Substring(0, 1),
line.Substring(1, 1),
line.Substring(2, 1));
}
}
}
No, it's best to keep the MyType class separate. It has one purpose, to represent whatever it represents. If it does that then it's perfect and doesn't need to change. (Look at the Single Responsibility Principle.)
In most cases it makes sense to do exactly what you're doing. Another class has its own responsibility, to take some input - a file, the results of a SQL query, etc., and read it into a class or collection of classes.
Sometimes if it gets complicated it's good to break it down even further - perhaps one class reads from a file and other converts a record from the file into a class. But that's often overkill. At most it's usually enough to break those up into separate methods in one class.
The only case I can think of where a class "owns" the function of parsing something is with value types like int or DateTime or classes like IpAddress where string representations are so common that it makes sense to have methods like int.Parse(string) or DateTime.Parse(string). But that wouldn't make sense for something more complex like parsing a record from a file or a SQL record.
I'm starting to learn C# for WP7, I'm making an app to scrape various sites and display a couple of items of info off the page.
I'm going to allow the user to create multiple "accounts" on the phone - each is a set of login details for a particular site. For example, if I was to use stackoverflow as an example, I'd have a class:
public abstract class MyBaseClass
{
public Dictionary<string, string> fields;
}
public class StackOverflow : MyBaseClass
{
public StackOverflow()
{
fields.Add("Username", "Default Username");
fields.Add("Password", "");
}
}
The class will do all the work, I want people to be able to submit new classes for inclusion in later releases.
The application will iterate over each of the fields, displaying the appropriate form field to the user. Once completed, the UI will update the dictionary, ready to start scraping.
Using a dictionary seemed ok to start, but I hadn't thought about how to represent the data type - I want to define whether the input should be text, number, or password.
How would I best include that data?
Given that screen-scraping is bad at best and disasterous at worst, I must recommend that you only include sites (or serviecs) that provide a public documented API and then use that reference to define the data types that you are storing.
That said, if you're on C#/.NET 4 you might want to use the Tuple data type.
One thing to keep in mind with this pattern is that pretty much everything you do with this object is based on a "magic string". String data has very little that can be checked at compile-time; a field name referenced as a string may have a spelling mistake that would be caught immediately by the compiler; similarly, setting "ABC123" as a field that was supposed to be a decimal is just fine 'til you try and parse it out.
If you're determined to go down this path, I would change the Dictionary to a List of a custom class that contained all the metadata of the field; its name, its type, current value, etc. The list should be protected, and accessed via one or more indexers on the class that derives from your MyBaseClass class, which can pull data based on an index position OR by field name, as the situation may call for.
Be aware that in changing to a List, the naive implementation would result in a linear search time for a field, while a Dictionary gives you logarithmic access time. You can mitigate this by sorting the list and implementing a BinarySearch to find field names.
You are going to have to create your own model to represent this. Just do what comes naturally and makes sense. How about this:
public enum InputType
{
Text,
Number,
Password
}
public class Value
{
public object Value { get; set;}
public InputType InputType { get; set;}
}
public abstract class MyBaseClass
{
public Dictionary<string, Value> fields;
}
public class StackOverflow : MyBaseClass
{
public StackOverflow()
{
fields.Add("Username", new Value() {
Value = "Default Username",
InputType = InputType.Text
});
fields.Add("Password", new Value() {
Value = "hw78fksm9",
InputType = InputType.Password
});
}
}
By the way, don't make the fields variable of MyBaseClass public, this is an implementation detail and should be hidden / encapsulated!
I have a Report Interface which has a Run method.
There are different types of reports which implement this interface and each run their own kind of report, getting data from different tables.
Each report, using its own data context, gets data which then populates Business Objects with and at the moment they are returned as an array (I would like to be able to at least return something like a list but because you have to define the list type it makes it a bit more difficult).
Reflection is then used to find out the properties of the returned data.
I hope I have explained this well enough!
Is there a better way of doing this?
By request:
public interface IReport
{
int CustomerID { get; set; }
Array Run();
}
public class BasicReport : IReport
{
public int CustomerID { get; set; }
public virtual Array Run()
{
Array result = null;
using (BasicReportsDataContext brdc = new BasicReportsDataContext())
{
var queryResult = from j in brdc.Jobs
where j.CustomerID == CustomerID
select new JobRecord
{
JobNumber = j.JobNumber,
CustomerName = c.CustomerName
};
result = queryResult.ToArray();
}
}
}
The other class then does a foreach over the data, and uses reflection to find out the field names and values and puts that in an xml file.
As it stands everything works - I just can't help thinking there is a better way of doing it - that perhaps my limited understanding of C# doesn't allow me to see yet.
Personnally I would first ask myself if I Really need an interface. It would be the case if the classes implementing it are Really different by nature (not only by report kind).
If not, i.e all the implementing classes are basically "Reporters", then yes, there is a more convenient way to do this which is :
Writing a parent abstract Report
Having a virtual Run method and the CustomerID accessor
inheriting your "Reporter" classes from it