|
"Factories" typically create "new" (empty) objects; you're simply restoring from existing data. Your static (data) collections constitute "data repositories".
So, calling your classes "factories" is a misnomer.
"Before entering on an understanding, I have meditated for a long time, and have foreseen what might happen. It is not genius which reveals to me suddenly, secretly, what I have to say or to do in a circumstance unexpected by other people; it is reflection, it is meditation." - Napoleon I
|
|
|
|
|
I was mistaken. You are right; classes those are. I was just informed that by someone on another forum. Now I need to figure out if I want to go factory with them, then abstract factory, or XML serialization, like someone else suggested. Which one would be the better choice? I have seven so-called factories in the game/tutorial I've been following.
|
|
|
|
|
I think you need a better handle on serializing a class. I think you have an opportunity to make your code more "generic" (which means fewer lines).
Examples of XML Serialization | Microsoft Docs
Generic Methods - C# Programming Guide | Microsoft Docs
Maybe your tutorial "started" with XML; in my case, for game tables, I typically build them in code as classes, and serialize / deserialize them to / from XML, if needed. Just find them easier to maintain and integrate that way; even for 100 entries or so. Stick everything in a "data class library".
"Before entering on an understanding, I have meditated for a long time, and have foreseen what might happen. It is not genius which reveals to me suddenly, secretly, what I have to say or to do in a circumstance unexpected by other people; it is reflection, it is meditation." - Napoleon I
modified 21-Dec-21 16:18pm.
|
|
|
|
|
Would XML serialization be better for what I'm trying to do? Some of the factory classes will have a lot of subtypes in them, so wouldn't a factory or abstract factory be better? Let's say, for example. I took Itemfactory.cs, gameitem.cs, and Inventory.cs wouldn't those benefit from being a factory or even abstract factory?
itemfactory.cs
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml;
using Engine.Actions;
using Engine.Models;
using Engine.Shared;
using SOSCSRPG.Core;
namespace Engine.Factories
{
public static class ItemFactory
{
private const string GAME_DATA_FILENAME =
".\\GameData\\GameItems.xml";
private static readonly List<GameItem> _standardGameItems = new
List<GameItem>
();
static ItemFactory()
{
if(File.Exists(GAME_DATA_FILENAME))
{
XmlDocument data = new XmlDocument();
data.LoadXml(File.ReadAllText(GAME_DATA_FILENAME));
LoadItemsFromNodes(data.SelectNodes("/GameItems/Weapons/Weapon"));
LoadItemsFromNodes(data.SelectNodes("/GameItems/HealingItems/HealingItem"));
LoadItemsFromNodes(data.SelectNodes("/GameItems/MiscellaneousItems/MiscellaneousItem"));
}
else
{
throw new FileNotFoundException($"Missing data file:
{GAME_DATA_FILENAME}");
}
}
public static GameItem CreateGameItem(int itemTypeID)
{
return _standardGameItems.FirstOrDefault(item =>
item.ItemTypeID ==
itemTypeID)?.Clone();
}
private static void LoadItemsFromNodes(XmlNodeList nodes)
{
if(nodes == null)
{
return;
}
foreach(XmlNode node in nodes)
{
GameItem.ItemCategory itemCategory =
DetermineItemCategory(node.Name);
GameItem gameItem =
new GameItem(itemCategory,
node.AttributeAsInt("ID"),
node.AttributeAsString("Name"),
node.AttributeAsInt("Price"),
itemCategory ==
GameItem.ItemCategory.Weapon);
if(itemCategory == GameItem.ItemCategory.Weapon)
{
gameItem.Action =
new AttackWithWeapon(gameItem,
node.AttributeAsString("DamageDice"));
}
else if(itemCategory ==
GameItem.ItemCategory.Consumable)
{
gameItem.Action =
new Heal(gameItem,
node.AttributeAsInt("HitPointsToHeal"));
}
_standardGameItems.Add(gameItem);
}
}
private static GameItem.ItemCategory
DetermineItemCategory(string itemType)
{
switch(itemType)
{
case "Weapon":
return GameItem.ItemCategory.Weapon;
case "HealingItem":
return GameItem.ItemCategory.Consumable;
default:
return GameItem.ItemCategory.Miscellaneous;
}
}
}
}
gameitem.cs
using Engine.Actions;
using Newtonsoft.Json;
namespace Engine.Models
{
public class GameItem
{
public enum ItemCategory
{
Miscellaneous,
Weapon,
Consumable
}
[JsonIgnore]
public ItemCategory Category { get; }
public int ItemTypeID { get; }
[JsonIgnore]
public string Name { get; }
[JsonIgnore]
public int Price { get; }
[JsonIgnore]
public bool IsUnique { get; }
[JsonIgnore]
public IAction Action { get; set; }
public GameItem(ItemCategory category, int itemTypeID, string name, int price,
bool isUnique = false, IAction action = null)
{
Category = category;
ItemTypeID = itemTypeID;
Name = name;
Price = price;
IsUnique = isUnique;
Action = action;
}
public void PerformAction(LivingEntity actor, LivingEntity target)
{
Action?.Execute(actor, target);
}
public GameItem Clone()
{
return new GameItem(Category, ItemTypeID, Name, Price, IsUnique, Action);
}
}
}
Inventory.cs
using System.Collections.Generic;
using System.Linq;
using Engine.Shared;
using Newtonsoft.Json;
namespace Engine.Models
{
public class Inventory
{
#region Backing variables
private readonly List<GameItem> _backingInventory =
new List<GameItem>();
private readonly List<GroupedInventoryItem> _backingGroupedInventoryItems =
new List<GroupedInventoryItem>();
#endregion
#region Properties
public IReadOnlyList<GameItem> Items => _backingInventory.AsReadOnly();
[JsonIgnore]
public IReadOnlyList<GroupedInventoryItem> GroupedInventory =>
_backingGroupedInventoryItems.AsReadOnly();
[JsonIgnore]
public IReadOnlyList<GameItem> Weapons =>
_backingInventory.ItemsThatAre(GameItem.ItemCategory.Weapon).AsReadOnly();
[JsonIgnore]
public IReadOnlyList<GameItem> Consumables =>
_backingInventory.ItemsThatAre(GameItem.ItemCategory.Consumable).AsReadOnly();
[JsonIgnore]
public bool HasConsumable => Consumables.Any();
#endregion
#region Constructors
public Inventory(IEnumerable<GameItem> items = null)
{
if(items == null)
{
return;
}
foreach(GameItem item in items)
{
_backingInventory.Add(item);
AddItemToGroupedInventory(item);
}
}
#endregion
#region Public functions
public bool HasAllTheseItems(IEnumerable<ItemQuantity> items)
{
return items.All(item => Items.Count(i => i.ItemTypeID == item.ItemID) >= item.Quantity);
}
public Inventory AddItem(GameItem item)
{
return AddItems(new List<GameItem> { item });
}
public Inventory AddItems(IEnumerable<GameItem> items)
{
return new Inventory(Items.Concat(items));
}
public Inventory RemoveItem(GameItem item)
{
return RemoveItems(new List<GameItem> { item });
}
public Inventory RemoveItems(IEnumerable<GameItem> items)
{
List<GameItem> workingInventory = Items.ToList();
IEnumerable<GameItem> itemsToRemove = items.ToList();
foreach (GameItem item in itemsToRemove)
{
workingInventory.Remove(item);
}
return new Inventory(workingInventory);
}
public Inventory RemoveItems(IEnumerable<ItemQuantity> itemQuantities)
{
Inventory workingInventory = new Inventory(Items);
foreach (ItemQuantity itemQuantity in itemQuantities)
{
for (int i = 0; i < itemQuantity.Quantity; i++)
{
workingInventory =
workingInventory
.RemoveItem(workingInventory
.Items
.First(item => item.ItemTypeID == itemQuantity.ItemID));
}
}
return workingInventory;
}
#endregion
#region Private functions
private void AddItemToGroupedInventory(GameItem item)
{
if(item.IsUnique)
{
_backingGroupedInventoryItems.Add(new GroupedInventoryItem(item, 1));
}
else
{
if(_backingGroupedInventoryItems.All(gi => gi.Item.ItemTypeID != item.ItemTypeID))
{
_backingGroupedInventoryItems.Add(new GroupedInventoryItem(item, 0));
}
_backingGroupedInventoryItems.First(gi => gi.Item.ItemTypeID ==
item.ItemTypeID).Quantity++;
}
}
#endregion
}
}
modified 21-Dec-21 19:30pm.
|
|
|
|
|
Me telling you to use XML serializing (or not) will do you no good until you understand the process better; that's what the links are for; including any links in the article.
One typically "saves" (things like inventory) when you expect to quit and restart a game (restore); that's a valid context for serialization. The rest is up to you.
"Before entering on an understanding, I have meditated for a long time, and have foreseen what might happen. It is not genius which reveals to me suddenly, secretly, what I have to say or to do in a circumstance unexpected by other people; it is reflection, it is meditation." - Napoleon I
|
|
|
|
|
i see i will look in to that i've been reading up on the links trying to get a better understanding
|
|
|
|
|
Hey all,
I am currently downloading files for .net desktop development workload.
Just wondering - is there any way to retrieve the installer files for offline installation should I need it in the future?
Cheers
|
|
|
|
|
What, you think MS is going to go bust and Visual Studio will disappear overnight?
See here: Create an offline installation - Visual Studio (Windows) | Microsoft Docs[^]
BTW: you need to learn to google first - it took me less than 10 seconds to find that starting with a "Visual Studio ISO" search and following a link from a result link ... You will save a lot of time if you get used to researching with it first!
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
"Common sense is so rare these days, it should be classified as a super power" - Random T-shirt
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
Thanks... haha - no I'm planning an OS re-install soon so was trying to save myself the time downloading again.
Yes I did go and search it out beforehand - unfortunately, I chose the option to Download AND install rather than Download THEN install.
Should have made the question clearer, was trying to find out if there is a way to retrieve the install files from temp... but no worries, I reckon it would be a massive hassle even if there was a way - I'll just make sure I choose the right option next time!
Cheers
|
|
|
|
|
I have a textBox , when the user click on the button i read a table and make a foreach to read the rows and then display the data in the textbox.
The data in the txtMensaje has to display and change until the end, but only the last row is display.
Ex. if i have; data1, data2.data3....n
the first display data in the textbox should be data1, then data2 has to be display and so on.
But nothing happen
int fila = TNombre.Rows.Count;
if (fila > 0)
{
foreach (DataRow row in TNombre.Rows)
{
txtMensaje.Text = row[0].ToString();
}
}
Thanks
|
|
|
|
|
Try to do the same with a plain string variable, rather than txtMensaje.Text!
On each iteration, the string value is replaced. The last assignment applies.
If you want to append the lines, one after one other, you use +=, rather than = (regardless of whether you are appending to a plain string or the contents of a text box).
|
|
|
|
|
You can't use a loop for that: when an event is raised your handler is called and nothing else happens until your event handler hits the return statement (or the end of the method) - and that very much include display updates!
So reading the lines in a loop does nothing useful, because the Paint event isn't actioned until after the last line has been displayed - so the only thing your user will ever see is the last line!
If you want to do that, you will need to set up a Timer (with an Interval that says how long you want each line displayed for) and kick it off in your button Click event.
Inside the Timer.Tick handler, copy just one line to the textbox, and set up for the next by moving an index on one. Then exit (remembering to cancel the timer when you run out of lines).
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
"Common sense is so rare these days, it should be classified as a super power" - Random T-shirt
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
..looks more like he is overwriting the property with the contents of each row. Run it, and only the last row is visible.
I don't think he intends the user to click a button to get "one new row" of data, but I could be mistaken. If that's the intention, then simply load the table and use a pointer, instead of mucking with timers.
Bastard Programmer from Hell
"If you just follow the bacon Eddy, wherever it leads you, then you won't have to think about politics." -- Some Bell.
|
|
|
|
|
What I believe he expects is that each time round the loop a single line of text should be briefly visible - and a Timer is the best solution to that.
That's how I read the original post, anyway.
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
"Common sense is so rare these days, it should be classified as a super power" - Random T-shirt
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
That's also an option, true
Bastard Programmer from Hell
"If you just follow the bacon Eddy, wherever it leads you, then you won't have to think about politics." -- Some Bell.
|
|
|
|
|
Good morning,
I have been playing around with monthCalendar and been having some issues understanding if I can do something. In my program, my user gets paid on the 15th and EOM, I am trying to highlite each 15th as a paydate and then figure out each EOM and highlight that as well. But, it seems that all I can find is that you have to do "FULL" dates "2021, 12, 15", or am I missing something.
Is there a good tutorial out there to help me understand how to do what I want to do?
Richard
Disable Vet
Grandfather
Pain in the @ss
|
|
|
|
|
The first of the next month, minus one day.
|
|
|
|
|
|
You can use
DateTime today = DateTime.Now;
int lastDay = DateTime.DaysInMonth(today.Year, today.Month);
That particular example would return 31 for December 17 2021 (today's date).
".45 ACP - because shooting twice is just silly" - JSOP, 2010 ----- You can never have too much ammo - unless you're swimming, or on fire. - JSOP, 2010 ----- When you pry the gun from my cold dead hands, be careful - the barrel will be very hot. - JSOP, 2013
|
|
|
|
|
I have a Visual C# .net application hosted on a git.
When I recently moved to a new laptop and re-installed visual studio, I cloned the repository succesfully, but i can not publish / run the application anymore because it's complaining about a lost "database.mdf" file.
error MSB3113: Could not find file 'AppData\Database.mdf'
error MSB3113: Could not find file 'AppData\Database_log.ldf
On my old laptop the location of the database was in the "AppData" directory. Offcourse it's not there anymore.
But my thought was that the project would re-create the database and make a whole new one.
Is this still possible and how do I do this?
|
|
|
|
|
No, it's not. If it's not part of the git repository, it isn't included - just "accessing it from your code" doesn't make it part of the repository any more than a git-based project to write letters would automatically push each letter to the Git server.
Git is about source code, not data - it is not a backup system!
A database is data which in your case resides on your laptop: that isn't part of your Git project, so it isn't added to the repository. You will have to copy it manually to your new device.
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
"Common sense is so rare these days, it should be classified as a super power" - Random T-shirt
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
If the database wasn't part of your project checkin, then you're going to have to recreate it manually.
This is precisely why I don't use MDF files. Instead I use SQL Server instance on a different box, rather than my dev box. That way, when I move to a different system, the database is always there (assuming the server box itself hasn't gone tits up).
".45 ACP - because shooting twice is just silly" - JSOP, 2010 ----- You can never have too much ammo - unless you're swimming, or on fire. - JSOP, 2010 ----- When you pry the gun from my cold dead hands, be careful - the barrel will be very hot. - JSOP, 2013
|
|
|
|
|
Err...and of course presumably back ups of the db are being taken.
|
|
|
|
|
Hello, i have trie this code and i get only the values of the date selectionned, but i need to show if the currect date does not exist, to show the previews values in crystal repor, how can i use previous () fonction?
for example
if ({myadate.datelqd}={?date}) then{mydate.restrlqd}={mydate.restrlqd}
else if mydate does not exists then show previews value
here is what i have tried
if ({?date}={mydate.datelqd}) then {mydate.restrlqd}={mydate.restrlqd}
but I want that when the requested date is not in the database, that I display the last recording for example
on 10/12/2021 i have qty = 55
on 13/12/2021 i qty = 85
on 14/12/2021 I have qty = 55
when I enter 12/12/2021 for example, let it display the data for 10/12/2021 where the qty = 55
modified 14-Dec-21 14:52pm.
|
|
|
|
|
|