How to model the Document class? - c#

I'm using a document class. The first time, it was for the common files with methods like New(), Open(), Save().
New() and Open() returns a IDocument. Save doesn't return anything.
As you can see in the diagram above.
In my program, it must use xml or zip file extension. For the xml files there's any problem, all the methods are for it. But I've got problems with zip file. I was planning to do this, when the program executes Open(), extract all the xml files from the zip and returns all the files. But my Open() only returns a document.
I was planning of creating another property called CanExtract(), but maybe this is not a good idea. I just want to create a good design and understandable.

Change your Open() function to return an IEnumerable of IDocument:
public IEnumerable<IDocument> Open()
instead of
public IDocument Open()
Then when you open an xml file it returns an IEnumerable containing 1 IDocument and you can just use that one. When you open the zip file it returns all of the files in the zip as IDocuments inside the IEnumerable.

I would recommend changing your return property to be a List. Then you can process the list of documents with the same code whether there is 1 or 20 files returned.
You could also add overloads for creation and saving that accept multiple files and, if those overloads are used, you could perform automatic zipping.

Related

Is reading csv file from physical path is valid scenario in unit test case ? why?

string _inboundFilePath = AppDomain.CurrentDomain.BaseDirectory + #"\Inbound\CompareDataFile.csv";
var mockReaderStream = new Mock<IReaderStream>();
mockReaderStream.Setup(x => x.CreateStream())
.Returns(new System.IO.StreamReader(_inboundFilePath));
Here I am dependent on an inbound file to read data from and then perform other function checks. my question is how to avoid this? In this case I am checking data for a particular id that comes in from the csv.
It is not likely to be a good practice because a unit test must be deterministic. It means that whatever the situation, you must be sure that if this test runs, it will do exactly the same than before.
If you read a csv file, the test will depend on the external world. And unfortunately, the external world is not stable. For a start somebody can change the csv file.
That is why it is a better practice to get the csv file stream from a an embedded resource in the assembly instead of getting it from a file on the hard drive.
In addition to the answer from Stephane. I will suggest you:
Put #"\Inbound\CompareDataFile.csv" to config file.
Create public property or separate method in the aforementioned class that will be able to retrieve and return the inbound file absolute path (call it GetPath).
Create UnitTest method that have access to the config file. This TestMethod must read config files, call AppDomain.CurrentDomain.BaseDirectory. So this method could also retrieve the path of inbound file absolute path and after this call GetPath()
Create abstraction (interface or abstract class above Mock - (it's not a mock by the way in the code you've provided, so hard to guess why you call it so)).
Create public method in the aforementioned class that will require an object of the abstraction and call its method ReadFromCsv().
Create Test class (mock) that will implement this abstraction and will return desired/undesired values when you call it's method ReadFromCsv().
Finally, test your class.
PS. This is not a strict algorithm of testing the class, you can use it. By what you would like to get from all this seven items is the notion of unit-test-likeness.
Also you do not free your class from config file, so, use this approach to free your class from config:
How to mock ConfigurationManager.AppSettings with moq

How to write a Wix Custom Action to Read XML data and set Properties

I have been working on this for days and I just don't get the concept of how Custom Actions work with Wix. Or at least I don't see how to do what I want.
I have several XML files that I want to read a value from and populate a property that gets displayed in a UI Dialog. Then when the install begins update that value in another XML file.
I need to be able to pass the filename including path of the local XML file and the node to search for and the key value pair to extract. I also need to pass what property needs to be updated.
I understand the CustomAction DLL concept. And that the session.CustomActionData["parametername"] syntax for passing in parameters. And the session["property"] = to set a property.
But I can't figure out the syntax of the wsx code to make it all happen. I read different examples doing it different ways?
I searched all the Google links out there an nothing seems to fit what I want to do?
You want this to be an immediate custom action not a deferred custom action so CustomActionData has no relevance to you.
What I would do is write a custom table like such:
Id [PK]
File (Formatted)
XPATH
Property
Here's an example:
mySearch
[SOMEPROPERTY]
/test[#'test'] (something like that, I hate xpath)
MYPROPERTY
You can use things like Property/FileSearch to have MSI's AppSearch resolve the location of a file and assign it to [SOMEPROPERTY]. Then you write a custom action scheduled after AppSearch to fetch this table's data, iterate it and fetch the attribute value (or element innertext) of each row and assign it to MYPROPERTY.
InstallShield gave this to me for free. I don't think WiX has a built in extension to do this. Maybe there is a community extension out there. It would probably take me an hour to write a prototype of this in C#/DTF.

fastest way to search and delete files inside a directory

I've got a array of class in which one member is the full path to a file. I need to delete all those files from the directory which is not included in the array. As Usual, I am using the convential compare and delete method. I need to know if there any fast way to accomplish this.
I heard it can be done using Linq, but i dont have knowledge on linq.
My class struct is like below.
Class ImageDetails
{
public string Title;
public Boolean CanShow;
public String PathToFile;
}
I have an array of ImageDetails. The PathToFile contains full path
}
You can use Except() to handle this:
var filesToDelete = Directory.GetFiles(Path.GetDirectoryName(yourClass.FilePath)).Except(yourClass.TheArray);
Why do you need to compare? If you have the full file name, then
File.Delete(fileName);
is all you need. The file IO is likely to be the slowest part of this, so I don't think Linq will make much difference to the performance.
If the file may not exist, then check for that first:
if (File.Exists(fileName))
{
File.Delete(fileName);
}
Edit: I see you mean that you want to delete the file if it is not in the array. I read your question to mean that the directory is not included in the array.
Still, the actual file deletion is likely to be the slowest part of this.

Best way to represent text in memory

I have 2 classes that inherit from a common base class.
Each of these specialized classes load some data from a data base, process it and then save that information in text files.
The first class represents the information as a XML document.
The second class will store its information as a text file with delimiters separating fields.
What I want to do is to write a single Save method in the base class that can be used by both classes. As all classes will write to text files I was thinking in use a common representation to store their data in memory - for instance the first class will transform the XmlDocument to that common representation.
What is the best way to store this in memory, string, Stream?
Thanks
If the derived classes represent the data very differently, don't implement a common Save method for them, Those classes knows best how to Save their data.
Make Save() abstract and have each of the subclass implement the saving.
There might be something in common for doing a Save() (e.g. opening the actual file, error handling). So have your base class provide a Save() method that's responsible for that which in turn calls a virtual Save(System.IO.TextWriter writer); method that each of your subclasses implement.
Given that XML is the richer of the two formats you mention, and relatively easy to manipulate, why not have a single representation and 2 save methods?
If the input data is uniformly structured, you can likely store it cleanly in a DataSet, and maybe load directly from your XML using DataSet.ReadXml on a TextReader input.
If you only have one type of record to output to the delimited textfile, DataTable could be used directly - a DataSet encapsulates multiple DataTables.
Another alternative might be to convert XML directly to CSV (comma = delimiter here, you could use whatever you wanted though) using XSLT as shown here by #Welbog.

Write DB information to a file - good appraoch?

I have a DB and a mapping framework which was written by the company Im working for. So I have a class for each table in the DB and those classes allow to call the DB and get various information in DataSets or DataTables for example. Now I am supposed to write that information to a TXT file in a certain format (I have the specs how it should look like). Its about estates, there will be many estates in a file and for each estates there are about 40 lines in the file. I know how to write to a file and stuff, what I am looking for is a good approach how to build this functionality in general.
This might be too general to give good advice, but is there a proven way to do such things?
Thanks :-)
Let's call the classes that give you table info TableInfo objects
I'd create an interface IDBInfoWriter, with a method WriteDBInfo(TableInfo ti)
Then an implementation of IDBInfoWriter, say DBInfoFileWriter, with a FileWriter as a private member. Each call to WriteDBInfo would dump whatever in the file writer
Finally a DBInfoWalker object, which would take a list of instantiated TableInfo and a IDbInfoWriter
class DBInfoWalker
function new(TableInfo[] tis, IDBInfoWriter idbiw)
{...}
function process()
{
for each TableInfo ti in tis
{
idbiw.WriteDBInfo(ti);
}
}
This way you can
Work on any subset of TableInfo you want (lets say you want just a list of TableInfo beginning with "S", pass only this list in the constructor of DBInfoWalker
Create as many output styles for your tableInfo, just create the correct implementation of IDBInfoWriter (network, unique file, multiple files, etc)
Of course, that's just one possibility :)
Good luck

Categories

Resources