I have this sample data. Right now it is defined in a seperate C# file like this:
public class SampleData{
public static ObservableCollection<Product> GetSampleData(){
ObservableCollection<Product> teams = new ObservableCollection<Product>();
}
}
and I load the obsevableCollection inside GetSampleData().
It works and I am able to get the Sample-Data anywhere in my program.
But how can I redesign this code so that I can create the sample data on the fly from outside the class?
What you are trying to implement is called a singleton pattern. It allows you to store a single instance of an object.
Basically your problem is that every time you call GetSampleData you are creating a new instance of the ObservableCollection<Product> so you can’t get the same data gain by calling the method again. Your actual sample I think is not what you meant because in it’s posted form it wouldn’t compile because you missed the return teams;.
I am guessing you want something like this:
public class SampleData
{
private static ObservableCollection<Product> _Instance;
public static ObservableCollection<Product> Instance
{
get
{
// Create a new collection if required.
if (SampleData._Instance == null)
{
// Cache instance in static field.
SampleData._Instance = new ObservableCollection<Product>();
}
// Return new or existing collection.
return SampleData._Instance;
}
}
}
Basically we are creating the object instance on the first call so when you call the Instance property again you get the same instance.
Use it like this:
// Add the data to the ObservableCollection<Product>.
SampleData.Instance.Add(new dataObjectOrWhatEver());
// Get index 0 from the collection.
var someObject = SampleData.Instance[0];
public class SampleData{
static ObservableCollection<Product> teams = null;
static public ObservableCollection<Product> Teams{
get{
if(teams == null)
teams = GetSampleData();
return teams;
}
set{
teams = value;
}
}
// make this one private
private static ObservableCollection<Product> GetSampleData(){
ObservableCollection<Product> t = new ObservableCollection<Product>();
// fill t with your data
return t;
}
}
AND for the cunsumer:
public class MyCunsumerClass{
// the method that uses the Team that provided by SampleData
public void MyMethod(){
this.flatteningTreeView.ItemsSource = SampleData.Teams;
}
public void MyFillerMethod(){
var my_new_data = new ObservableCollection<Product>(); // or anything else you want to fill the Team with it.
SampleData.Teams = my_new_data;
// SampleData.Teams has new value you suplied!
}
public void MyChangerMethod(){
var t = SampleData.Team;
t.AnyProperty = my_value;
t.OtherProperty = my_value_2;
// SampleData.Team's properties changed!
}
}
Related
I'm working on a product calculator program. Inside the app, the rep sale person can search for a client ID and the app shows him what services he can offer to client and his provision for sale. The form is generated acording to data i download from database.
Right now I'm trying to store generated controls in lists. Every time a search is made, I dispose of controls and clear the lists. The thing i cant seem to get working is to store all the lists in single dictionary.
Something like this...
public class ListOfControls<T> : IListOfControls<T> where T : Control
{
private readonly List<T> _controlsList;
public ListOfControls()
{
_controlsList = new List<T>();
}
public void AddControll(T control)
{
_controlsList.Add(control);
}
public T this[int number]
{
get
{
return _controlsList[number];
}
}
public void ClearControls()
{
_controlsList.Clear();
}
public T Last()
{
return _controlsList.Last();
}
}
class DictionaryOfControlsLists
{
//will be private - public only for test
public readonly Dictionary<string, IListOfControls<Control>> _dictionaryOfLists;
public DictionaryOfControlsLists()
{
_dictionaryOfLists = new Dictionary<string, IListOfControls<Control>>();
}
//Other code....
}
Now trying to implement...
DictionaryOfControlsLists _testDict = new DictionaryOfControlsLists();
_testDict._dictionaryOfLists.Add("test", new ListOfControls<Label>());
Sadly this wont work...Any ideas? THANKS
What you need is something like this:
class DictionaryOfControlsLists
{
private readonly Dictionary<Type, IListOfControls<Control>> _dictionaryOfLists = new Dictionary<Type, IListOfControls<Control>>();
public void Add<T>(T control) where T : Control
{
if (!_dictionaryOfLists.ContainsKey(typeof(T)))
{
_dictionaryOfLists[typeof(T)] = new ListOfControls<Control>();
}
_dictionaryOfLists[typeof(T)].AddControl(control);
}
public T Get<T>(int number) where T : Control
{
if (!_dictionaryOfLists.ContainsKey(typeof(T)))
{
_dictionaryOfLists[typeof(T)] = new ListOfControls<Control>();
}
return _dictionaryOfLists[typeof(T)][number] as T;
}
}
Then you can do this:
DictionaryOfControlsLists _testDict = new DictionaryOfControlsLists();
_testDict.Add<Label>(new Label());
Label label = _testDict.Get<Label>(0);
If you need to extend this to have a string key then you need to implement a double dictionary within DictionaryOfControlsLists to handle it - something like a Dictionary<Type, Dictionary<string, IListOfControls<Control>>>.
I am creating a helper class for my MVC application. This class will contain static methods that will pull information the first time the user logs into the system.
I have created two methods that will return lists like list of countries and list of languages. I don't want to execute this every time but save results of first call and return it for subsequent calls.
public static List<Languages> GetLanguages()
{
using (var db = new MCREntities())
{
var languages = db.spGetLanguages(0);
return Mapper.Map<List<Languages>>(languages);
}
}
public static List<Countries> GetCountries()
{
using (var db = new MCREntities())
{
var countries = db.spGetAllCountries("");
return Mapper.Map<List<Countries>>(countries);
}
}
Inside your class you can have static list which would hold Languages anly first time would try to access database.
private static List<Languages> _languages = null;
public static List<Languages> GetLanguages()
{
if(_languages == null){
using (var db = new MCREntities())
{
var languages = db.spGetLanguages(0);
_languages = Mapper.Map<List<Languages>>(languages);
}
}
return _languages;
}
Alternatively, you can implement cache
i would say create a class with the required properties liek
public static class CurrentSession{
List<Languages> lang{get;set;}
List<Countries> countries{get;set;}
}
and in global.asax file
protected void Application_Start()
{
//.........predefined codes
CurrentSession.lang = GetLanguages();
CurrentSession.Countries =GetCountries();
I have a type mismatch error when reading the contents of table 'ImageHighlight'.
In designer.cs the table is:
public System.Data.Linq.Table<ImageHighlight>ImageHighlights
{
get
{
return this.GetTable<ImageHighlight>();
}
}
In my code I am trying to cache a small table in method LoadStaticCache() at ApplicationStart so I can access its contents later via GetHighlightImages().
public class StaticCache
{
private static ImageHighlight _images = null;
public static void LoadStaticCache()
{
// Get images - cache using a static member variable
using (var datacontext = new MHRDataContext())
{
_images = datacontext.ImageHighlights;
}
}
public static ImageHighlight GetHighlightImages()
{
return _images;
}
}
At code line _images = datacontext.ImageHighlights; I get error
Cannot implicitly convert type
System.Data.Linq.Table<HolidayRentals.Core.Domain.LinqToSql.ImageHighlight>
to HolidayRentals.Core.Domain.LinqToSql.ImageHighlight
They are both the same type.
datacontext.ImageHighlights is a Table which is an IQueryable of ImageHighlight. _imagess type is ImageHighlight. You can not convert these types to each other.
Since you want some caching mechanism and _images indicates that it should contain multiple instance of images then you should change the type of _images.
Change your code to this:
public class StaticCache
{
private static List<ImageHighlight> _images = null;
public static void LoadStaticCache()
{
// Get images - cache using a static member variable
using (var datacontext = new MHRDataContext())
{
_images = datacontext.ImageHighlights.ToList();
}
}
public static List<ImageHighlight> GetHighlightImages()
{
return _images;
}
}
I have a few static Dictionary object that holds some constants list for me so I wouldn't have to load them from database each time my website loads (for example: a list of countries, a list of categories).
So I have a static function that checks if the instance is null, and if it is query the database, instantiate the static variable, and populate it with data.
Since it is a website, there could be a case that more than one person tries to access that information at the same time while the object is null, and all those who do will call that process at the same time (which is really not necessary, causes unneeded queries against the DB, and could cause duplicated objects in the list).
I know there's a way to make this kind of loading thread-safe (just not really sure how) - could someone point me in the right direction? should I use a lock?
Thanks
UPDATE II:
This is what I wrote (is this a good thread-safe code?)
private static Lazy<List<ICountry>> _countries = new Lazy<List<ICountry>>(loadCountries);
private static List<ICountry> loadCountries()
{
List<ICountry> result = new List<ICountry>();
DataTable dtCountries = SqlHelper.ExecuteDataTable("stp_Data_Countries_Get");
foreach (DataRow dr in dtCountries.Rows)
{
result.Add(new Country
{
ID = Convert.ToInt32(dr["CountryId"]),
Name = dr["Name"].ToString()
});
}
return result;
}
public static List<ICountry> GetAllCountries()
{
return _countries.Value;
}
You can use Lazy to load a resource in a lazy and thread-safe manner:
Lazy<List<string>> countries =
new Lazy<List<string>>(()=> /* get your countries from db */);
Update:
public static class HelperTables
{
private static Lazy<List<ICountry>> _countries;
static HelperTables //Static constructor
{
//Instantiating the lazy object in the static constructor will prevent race conditions
_countries = new Lazy<List<ICountry>>(() =>
{
List<ICountry> result = new List<ICountry>();
DataTable dtCountries = SqlHelper.ExecuteDataTable("stp_Data_Countries_Get");
foreach (DataRow dr in dtCountries.Rows)
{
result.Add(new Country
{
ID = Convert.ToInt32(dr["CountryId"]),
Name = dr["Name"].ToString()
});
}
return result;
});
}
public static List<ICountry> GetAllCountries()
{
return _countries.Value;
}
}
If you're using .NET 4.0, you can use the builtin Lazy generic class.
private static Lazy<YourObject> data = new Lazy<YourObject>(YourInitializationFunction);
public static YourObject Data { get { return data.Value; } }
Note that you have to add a static constructor to the class where you define this, otherwise it's not completely thread-safe.
If you're not on .NET 4.0+, you can just write your own code. The basic pattern looks something like this:
private static YourObject data;
private static object syncObject = new object();
public static YourObject Data
{
get
{
if (data == null)
{
lock (syncObject)
{
if (data != null)
return data;
var obj = new YourObject();
return (YourObject)Interlocked.Exchange(ref data, obj);
}
}
return data;
}
}
I have a class named "CollectionPager" which has a collection inside that of type List. I have a method "RetrieveList" which takes a "CollectionPager" as input and populates "List" in side that. This method doesn't return any value.
I need to mock a function which calls "RetrieveList". However, since it doesn't return any value, whatever input was fed into Mock is not taken into consideration and this collection(List) always has a count of 0.
Any possible ways to resolve this?
I guess you need the Callback (see also Moq quickstart) method to setup some logic when mocking a void function.
Here is sample test which demonstrates the usage:
var mock = new Mock<IRetrieveListService>();
mock.Setup(m => m.RetrieveList(It.IsAny<CollectionPager>()))
.Callback<CollectionPager>(p =>
{
p.List.Add("testItem1");
p.List.Add("testItem2");
});
var sut = new OtherService(mock.Object);
sut.SomeMethodToTest();
Assuming your classes looks like something like these:
public class CollectionPager
{
public CollectionPager()
{
List = new List<string>();
}
public List<string> List { get; private set; }
}
public interface IRetrieveListService
{
void RetrieveList(CollectionPager pager);
}
public class RetrieveListService : IRetrieveListService
{
public void RetrieveList(CollectionPager pager)
{
pager.List.Add("item1");
pager.List.Add("item2");
}
}
public class OtherService
{
private readonly IRetrieveListService retrieveListService;
public OtherService(IRetrieveListService retrieveListService)
{
this.retrieveListService = retrieveListService;
}
public void SomeMethodToTest()
{
var collectionPager = new CollectionPager();
retrieveListService.RetrieveList(collectionPager);
// in your test collectionPager.Item contains: testItem1, testItem2
}
}