Adding a Non-Static Class to a static List - c#

I have a Non Static class which contains a number of properties
private static List<FileClass> FileClassList = new List<FileClass>();
internal void AddFile(Alphaleonis.Win32.Filesystem.FileInfo finfo)
{
this.FileID = FileIDCounter;
this.Name = finfo.Name;
this.FullName = finfo.FullName;
this.Attributes = GetFileAttributes(finfo);
this.CreationTime = finfo.CreationTime;
this.Extension = finfo.Extension;
this.isReadOnly = finfo.IsReadOnly;
this.LastAccessTime = finfo.LastAccessTime;
this.LastWriteTime = finfo.LastWriteTime;
this.Length = finfo.Length;
Interlocked.Increment(ref FileIDCounter); // As a Static value this is shared amongst all the instances of the class
// Interlocked.Increment is the Thread Safe way of saying FileIDCounter ++;
FileClassList.Add(this);
if (FileClassFileAdded != null) FileClassFileAdded(this);
}
Although the Class is added FileClassList.Add(this); the final result is a FileClassList filled with whatever the last instance of the class contained and not the this.Properties values.
So, how do I add the current instance of the FileClass to the FileClassList so that the contents of the FileClassList contains the different instances of the FileClass.

Here is what your issue most likely is...
Having this:
internal void AddFile(Alphaleonis.Win32.Filesystem.FileInfo finfo)
Somewhere you probably do:
MyClassWhichAddsAFile cls = new MyClassWhichAddsAFile();
cls.AddFile(fileInfo1);
cls.AddFile(fileInfo2);
cls.AddFile(fileInfo3);
While you need to do (under this design):
MyClassWhichAddsAFile cls1 = new MyClassWhichAddsAFile();
cls1.AddFile(fileInfo1);
MyClassWhichAddsAFile cls2 = new MyClassWhichAddsAFile();
cls2.AddFile(fileInfo2);
........
Again, I am not discussing your design here or how to do it right. I am telling you that your problem is probably comes out from this situation

I think you have your design slightly askew. I don't think that AddFile should be part of FileClassList rather.
However in leiu of not having another place to hold it. I'd say do this:
internal static void AddFile(Alphaleonis.Win32.Filesystem.FileInfo finfo, FileClass theClass)
{
theClass.FileID = FileIDCounter;
theClass.Name = finfo.Name;
theClass.FullName = finfo.FullName;
theClass.Attributes = GetFileAttributes(finfo);
theClass.CreationTime = finfo.CreationTime;
theClass.Extension = finfo.Extension;
theClass.isReadOnly = finfo.IsReadOnly;
theClass.LastAccessTime = finfo.LastAccessTime;
theClass.LastWriteTime = finfo.LastWriteTime;
theClass.Length = finfo.Length;
Interlocked.Increment(ref FileIDCounter); // As a Static value this is shared amongst all the instances of the class
// Interlocked.Increment is the Thread Safe way of saying FileIDCounter ++;
FileClassList.Add(theClass);
if (FileClassFileAdded != null) FileClassFileAdded(theClass);
}
A better approach would be to create a contrstuctor on FileClass that takes a FileInfo and fills these properties in and call it like this:
var someFileClass = new FileClass(theFileInfo);
FileClass.AddFile(someClassFile);
and AddFile would be:
internal static void AddFile(Alphaleonis.Win32.Filesystem.FileInfo finfo, FileClass theClass)
{
Interlocked.Increment(ref FileIDCounter); // As a Static value this is shared amongst all the instances of the class
// Interlocked.Increment is the Thread Safe way of saying FileIDCounter ++;
FileClassList.Add(theClass);
if (FileClassFileAdded != null) FileClassFileAdded(theClass);
}
even then I think the AddFile should be a method on the the caller not the callee!

Related

Ban a variable from a list with a "ban" list

How can I ban a variable from a list without removing it from that list by adding the variable to a list of "banned" variable?
I wish to be able to type in a string. That string is compared to the file names in a folder. If there is a match, the file is read. If I type this same string again, the file should not be read again. There for I want to have a list of "banned" string that is checked whilst typing to avoid the file to be read again.
I have tried a few ways but not getting there. Below is an example of my last attempt.
What would be the best way?
public class test
{
string scl= "test3";
List <string> lsf,lso;
void Start ()
{
lsf=//file names
new List<string>();
lso=//files open
new List<string>();
lsf.Add("test0");
lsf.Add("test1");
lsf.Add("test2");
lsf.Add("test3");
lsf.Add("test4");
lso.Add("idhtk49fngo");//random string
}
void Update ()
{
if
(
Input.GetKeyDown("a")
)
{
for
(
int i=0;
i<lsf.Count;
i++
)
{
if(lsf[i]==scl)
{
Debug.Log
(i+" is read");
for
(
int j=0;
j<lso.Count;
j++
)
{
//how can i avoid reading
//lsf[3] here the second time
//"a" is pressed (by having "test3"
//added to a "ban" list (lso) )
if(scl!=lso[j])
{
lso.Add(lsf[i]);
}
}
}
}
}
}
Michael’s answer is the way to go here but it can be improved using the more appropriate collection available to keep track of opened files; if you want uniqueness use a set, not a list:
HashSet<string> openedFiles = new HashSet<string>();
public static bool TryFirstRead(
string path,
out string result)
{
if (openedFiles.Add(path))
{
result = File.ReadAllText(path);
return true;
}
result = null;
return false;
}
Also, I’d avoid throwing vexing exceptions. Give the consumer a friendly way to know if the file was read or not, don’t make them end up having to use exceptions as a flow control mechanism.
I didn't understand although if you want to replace a value from another list.
You can use the list index to create a new list with the values which you removed.
String list1 = {"hi", "hello", "World"};
String list2 = {"bye", "goodbye", "World"};
List1[1] = list2[1];
I would suggest such way:
public static List<string> openedFiles = new List<string>();
public static string ReadFileAndAddToOpenedList(string path)
{
if (openedFiles.Contains(path))
throw new Exception("File already opened");
// Instead of throwing exception you could for example just log this or do something else, like:
// Consolle.WriteLine("File already opened");
else
{
openedFiles.Add(path);
return File.ReadAllText(path);
}
}
The idea is - on every file read, add file to list, so you can check every time you try read file, if it was already read (or opened). If it is, throw exception (or do something else). Else read a file.
You could instead of making it a string list use your own class
public class MyFile
{
public string Name;
public bool isOpen;
public MyFile(string name)
{
Name = name;
isOpen = false;
}
}
List<MyFile> lsf = new List<MyFile>()
{
new MyFile("test0"),
new MyFile("test1"),
new MyFile("test2"),
new MyFile("test3"),
new MyFile("test4")
};
Than when you read the file set isOpen to true
MyFile[someIndex].isOpen = true;
and later you can check this
// E.g. skip in a loop
if(MyFile[someIndex]) continue;
You could than also use Linq in order to get a list of only unread files:
var unreadFiles = lsf.Select(f => f.Name).Where(file => !file.isOpen);

How prevent this loop?

I cannot figure out how to fix this loop issue when i call a function like
new Common.Utility.Parameter().Get(Common.Constants.Parameter.SomeParameter);
Probably the error is caused by isHttpsCookie that recall the Parameter.Get()
Utility.cs
public static class Utility
{
public class Parameter
{
public string Get(string key)
{
string cookie = new Cookie().Read(key);
if (cookie == null)
{
var parameter = new Models.Parameter();
using (var db = new MyEntities())
parameter = db.Parameters.Where(w => w.Key == key).FirstOrDefault<Models.Parameter>();
if (parameter != null)
{
new Cookie().Write(key, parameter.Value);
return parameter.Value;
}
else
return string.Empty;
}
else
return cookie;
}
}
}
Cookie.cs
public class Cookie
{
private bool isHttpsCookie = Convert.ToBoolean(new Utility.Parameter().Get(Constants.Parameter.IsHttps)); // Loop here?
public string Read(string cookieName)
{
HttpCookie httpCookie = HttpContext.Current.Request.Cookies[HttpContext.Current.ApplicationInstance.GetType().BaseType.Assembly.GetName().Na​me + "_" + cookieName];
return httpCookie != null ? HttpContext.Current.Server.HtmlEncode(httpCookie.Value).Trim() : string.Empty;
}
public void Write(string cookieName, string cookieValue, bool isHttpCookie = true)
{
if (isHttpsCookie)
isHttpCookie = false;
var aCookie = new HttpCookie(HttpContext.Current.ApplicationInstance.GetType().BaseType.Assembly.G​etName().Name + "_" + cookieName)
{Value = cookieValue, Expires = Common.Constants.Cookie.DefaultExpires, HttpOnly = isHttpCookie};
HttpContext.Current.Response.Cookies.Add(aCookie);
}
}
Apparently, your code is falling into a sort of recursion where you suspect it is. What I'm having trouble with is why are you creating new objects just to call a single method. Looks like you could have them as static methods in your classes, so no object creation would be needed, thus no 'looping'.
Have a closer look at your Cookie.Write() and Parameter.Get() method, they are calling each other. When you declare isHttpsCookie, you call Parameter.Get(). In the Parameter.Get(), if the condition is valid, it will call to Cookie.Write(). In its turn, when you call new Cookie(), the isHttpsCookie is called again and it's continuing forever.
Another point at this code:
if (isHttpsCookie)
isHttpCookie = false;
do you try to say that isHttpsCookie should be false at all time? so why do you need to declare this?
Solution: Do like #Takeshi said: those methods can be declared as static so no class declaration is required to called them.
You are correct in what you suspect. the isHttpsCookie declaration is causing you grief.
When the Cookie object is created it goes away and executes the method get from your utility class which creates an instance of cookie. Therefor you have your recursion.
You will need to change the way you initialise isHttpsCookie. Maybe only initialise / check if you are doing a write. After all you are most likely going to read more often than write.
Hope that helps.

Want to use a string to name a new instance of a class dynamically

Ok, this may be impossible but I want to use a string taken as an argument to a function and use that string to name a new instance of a class. Using visual studios 2010 with C# XNA, I tried searching for solutions using google and here but maybe I'm not using the right keywords or something.
public void createRace(string raceName, Element element1, Element element2, AbilityScore stat1, AbilityScore stat2, AbilityScore stat3, AbilityScore stat4)
{
Race temp = new Race();
temp.raceName = raceName;
temp.primaryElement = element1;
temp.secondaryElement = element2;
temp.primaryAbility = stat1;
temp.secondaryAbility1 = stat2;
temp.secondaryAbility2 = stat3;
temp.weakAbility = stat4;
}
I want Race temp to use raceName instead of temp when naming the new instance of Race, if it's not possible let me know and I'll find a workaround.
I would use a dictionary to solve this. The following code will allow you "raceName" based access to your instances
Dictionary<string,Race> races = new Dictionary<string,Race>();
public void createRace(string raceName, Element element1, Element element2, AbilityScore stat1, AbilityScore stat2, AbilityScore stat3, AbilityScore stat4)
{
Race temp = new Race();
temp.raceName = raceName;
temp.primaryElement = element1;
temp.secondaryElement = element2;
temp.primaryAbility = stat1;
temp.secondaryAbility1 = stat2;
temp.secondaryAbility2 = stat3;
temp.weakAbility = stat4;
races.Add(raceName,temp);
}

Mock void Method That Sets Private Setter in Implementations

I have an interface that looks like this...
public interface ITempFileNameBuilder
{
string DirectoryPath { get; }
string FileName { get; }
void GenerateNewFileName();
}
... and I want to mock the GenerateNewFileName method so that it sets the FileName property to something new. I know this is an odd request because obviously there is no set defined in the interface because it's declared as private set; in the two implementations. I did that so you must call GenerateNewFileName to set the FileName property to something new.
Is this possible?
Edit
Here is the unit of work I'm trying to test.
public void StartRecording(string claimNo, string ip_no, string ip_name, IWaveIn input, Stream writer)
{
if (this.IsRecording)
{
return;
}
if (_input != null)
{
_input.Dispose();
}
_input = input;
_input.WaveFormat = _waveFormat;
_input.DataAvailable += (s, args) =>
{
_writer.Write(args.Buffer, 0, args.BytesRecorded);
byte[] buffer = args.Buffer;
for (int index = 0; index < args.BytesRecorded; index += 2)
{
short sample = (short)((buffer[index + 1] << 8) | buffer[index + 0]);
float sample32 = sample / 32768f;
_aggregator.Add(sample32);
}
OnDataAvailable(args);
};
_input.RecordingStopped += (s, args) =>
{
_input.Dispose();
_writer.Dispose();
OnRecordingStopped(args);
};
if (this.CurrentRecording != null)
{
_tempFileNameBuilder.GenerateNewFileName();
}
this.Recordings.Add(new RecordingTrack(claimNo, ip_no, ip_name,
_tempFileNameBuilder.FileName,
_recordingDeployer,
_recordingCompressor));
if (this.MicrophoneLevel == default(float))
{
this.MicrophoneLevel = .75f;
}
_aggregator.Reset();
_writer = writer;
_input.StartRecording();
this.IsRecording = true;
}
And the goal of this unit test is to ensure that the FileName of the CurrentRecording and LastRecording are in fact different. It's a regression test based on a bug we found earlier. The bug was happening because the FileName property on the RecordingTrack was not being set but rather was just returning the current FileName from the ITempFileNameBuilder instance and so the idea is to ensure that GenerateNewFileName was called and ensure that the set for the TempFileName on the recording track was called.
However, the set on the TempFileName on the RecordingTrack is private too, it's done in the constructor, so maybe this isn't really a unit test and more so an integration test?
You're mocking the interface, not the implementation. So you should care about how the caller interacts with this. If you expect them to call GenerateNewFileName() and then access FileName, just expect those two calls and give back the appropriate results (where the "generated" filename can just be anything).
There's no "field" to set here - you're just talking about an API.
Of course, you could easily create a fake instead of a mock, and use that instead.
In a case like this, you need to use an explicit private field instead of the implicitly-generated one in the property. You'll need to make sure that implementations define the get method for the FileName property in terms of that private field.

Whats the correct way to dispose table adapters and data sets?

I've been working on a project that uses table adapters and datasets to access an access database. I'm near completion and ran code analysis from visual studio and it came up with some errors about needing to implement IDisposable on specific classes that I use these methods. While I've looked at a few different things on this about having a dispose method or using a using block, I'm not really sure how to make this work. The dataset and table adapters are created as global variables to be used by the whole class, many classes will call on other classes which will also use different table adapters and datasets. I've tried creating a Dispose method, but I don't know when to call it and I am wondering if it is called at the wrong time will it crash my program. Here is a sample of one of the classes that I need to implement Idisposable :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace recipeDataBase
{
class NewRecipe : IDisposable
{
recipiesNewDataSet recipeDataSet = new recipiesNewDataSet();
recipiesNewDataSetTableAdapters.RecipeTableAdapter recipeTableAdapter = new recipiesNewDataSetTableAdapters.RecipeTableAdapter();
recipiesNewDataSetTableAdapters.RecipeIngredientTableAdapter recipeIngredientTableAdapter = new recipiesNewDataSetTableAdapters.RecipeIngredientTableAdapter();
recipiesNewDataSetTableAdapters.RatingTableAdapter ratingTableAdapter = new recipiesNewDataSetTableAdapters.RatingTableAdapter();
recipeDataBase.recipiesNewDataSetTableAdapters.IngredientTableAdapter ingredientTableAdapter = new recipiesNewDataSetTableAdapters.IngredientTableAdapter();
private RecipeInfo newRecipe;
private RatingNum originalRatingNum;
private RatingNum newRating;
private RecipeInfo originalRecipe;
private string[] ingredients;
public NewRecipe(RecipeInfo incommingNewRecipe, RatingNum IncommingNewRating, string[] incommingIngredients)
{
newRecipe = incommingNewRecipe;
newRating = IncommingNewRating;
ingredients = incommingIngredients;
CreateNewRecipe();
UpdateNewRecipe();
}
public void CreateNewRecipe()
{
originalRatingNum = new RatingNum();
originalRecipe = new RecipeInfo();
originalRatingNum.cookingTime = 0;
originalRatingNum.easeOfCooking = 0;
originalRatingNum.familyRating = 0;
originalRatingNum.healthRating = 0;
originalRatingNum.userRating = 0;
ratingTableAdapter.Fill(recipeDataSet.Rating);
ratingTableAdapter.Insert(originalRatingNum.userRating, originalRatingNum.familyRating, originalRatingNum.healthRating, originalRatingNum.easeOfCooking, originalRatingNum.cookingTime);
Query getNewRecipeNumbers = new Query();
int newRatingNumber = getNewRecipeNumbers.newRatingNum();
originalRatingNum.ratingNum = newRatingNumber;
newRating.ratingNum = newRatingNumber;
newRecipe.ratingNum = newRatingNumber;
originalRecipe.recipeName = "newRecipe";
originalRecipe.nationality = "newRecipe";
originalRecipe.recipeEvent = "newRecipe";
originalRecipe.source = "newRecipe";
originalRecipe.type = "newRecipe";
originalRecipe.servings = "0";
originalRecipe.ratingNum = newRatingNumber;
recipeTableAdapter.Fill(recipeDataSet.Recipe);
recipeTableAdapter.Insert(originalRecipe.recipeName, originalRecipe.nationality, originalRecipe.recipeEvent, originalRecipe.source, originalRecipe.type, originalRecipe.servings, originalRecipe.ratingNum);
int newRecipeNum = getNewRecipeNumbers.newRecipeNum();
newRecipe.recipeNum = newRecipeNum;
originalRecipe.recipeNum = newRecipeNum;
recipeDataSet.AcceptChanges();
}
public void UpdateNewRecipe()
{
UpdateRatingNum updateRatingNum = new UpdateRatingNum(originalRatingNum, newRating);
UpdateRecipe updateRecipe = new UpdateRecipe(newRecipe, originalRecipe);
UpdateIngredients updateIngredients = new UpdateIngredients(ingredients);
UpdateRecipeIngredient updateRecpeIngredients = new UpdateRecipeIngredient(ingredients, newRecipe.recipeNum);
recipeDataSet.AcceptChanges();
}
public void Dispose()
{
ratingTableAdapter.Dispose();
recipeTableAdapter.Dispose();
recipeTableAdapter.Dispose();
ingredientTableAdapter.Dispose();
recipeDataSet.Dispose();
throw new NotImplementedException();
}
}
}
As you can see I did implement Idisposable and used the automatically created method to put all of the table adapters and dataset in there to be disposed, but how do I use it and where?
Thanks for the help
Craig
The normal pattern:
using (var nr = new NewRecipe() )
{
...
}
But a few notes here:
the IDisposable interfaces on DataSet and DataAdapter are dummies, you won't lose much when you skip them.
Your class has a dual role of Repository and Domain object. Consider separating it into 2 classes.
As mentioned in other answers the correct way to usage an object that implements IDisposable is withing a using block as follows:
using (var recipe = new NewRecipe())
{
//put your code that uses recipe here
}
What I would like to point out though is the correct implementation of the IDisposable pattern. Note that there is a complete example on the MSDN article for the IDisposable interface.
class Recipe : IDisposable
{
bool isDisposed = false;
TableAdapter myDisposableMember;
public void Dispose()
{
Dispose(true);
GC.SupressFinalize(this);
}
public virtual Dispose(bool isDisposing)
{
if (!isDisposed) //only clean up once
{
//clean up unmanaged resource here
//in this case we don't have any
//clean up managed resources (IE those that implemetn IDisposable only if
//Dispose() was called (not the case when invoked during finalisation)
if (isDisposing)
{
if(myDisposableMember == null)
{
myDisposableMember.Dispose()
myDisposablemember = null;
}
}
//mark this instance as cleaned up
isDisposed = true;
}
}
//if our class has any unmanaged resources you implement a destructor to guarantee
//that they're freed. We don't have any here so we don't implement it.
//~Recipe()
//{
// Dispose(false);
//}
}
Also note that you should NEVER throw an exception during finalization (IE: ~Recipe()). Consequently Dispose(bool) should NEVER throw an exception.
Correct way of using is using. Just don't take it in your hands -
using(DataAdapter ratingTableAdapter = new DataAdapter())
{
}
ratingTableAdapter will get disposed once the code comes out of the using block.

Categories

Resources