I am not sure if this is possible with C#, but is it possible to store information in an attribute that is related to the instance of a class?
So, I have the following class with the field Initialized, as seen here:
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class GameObjectAttribute : Attribute {
internal bool Initialized = false;
}
I then use this to add the attribute to the class:
[GameObject]
public class Player {
}
Now, in this class, is it possible to modify the data in the attribute for each individual instance of the class like in this pseudo code:
internal class Core {
async void Tick() {
while (isRunning) {
foreach (var gameObject in gameObjects) {
// Get attribute information
var refToAttribute = gameObject.... // Somehow get information
if (!refToAttribute.Initialized) {
// Do some stuff
refToAttribute.Initialized = true;
}
}
await Task.Delay(1);
}
}
}
Edit
When coming from a TypeScript world, I can return a new instance of a class when the class is created:
export function GameObject() {
return function (constructor: T) {
return class extends constructor {
initialized = false;
}
}
}
#GameObject
export class Player {
}
so now, in my loop I have access to instance, however Player does not have access.
Now, in this class, is it possible to modify the data in the attribute for each individual instance of the class
No, attributes are attached to the class, not to instances of said class. There is only a single instance of the attribute and that instance is attached to the class Player. You can access the attribute from the player instance, but only by looking at the attributes that are attached to the type. So it is really not anything that you could use to provide additional information for any particular player instance.
What you can do in a statically typed language is to wrap the value. Something like this would achieve what you are trying to do:
public class PlayerGameObject
{
public bool IsInitialized { get; set; }
public Player Player { get; set; }
}
// …
foreach (var gameObject in gameObjects)
{
if (!gameObject.IsInitialized)
{
var player = gameObject.Player;
// do some stuff
gameObject.IsInitialized = true;
}
}
is it possible to store information in an attribute that is related to the instance of a class?
No. Attributes are part of the definition of a class, not instances of it. It's impossible for the same reason that a method can't be public for one instance of a class but private for another instance of the same class.
Information about an instance of a class can only be stored in its fields and properties.
I suggest you use a base class instead.
//Your framework
abstract class GameObject
{
internal bool Initialized { get; set; } = false;
}
//Inside program that uses the framework
class Player : GameObject
{
}
Now the Player class has a property than only your code can access.
//Your framework
void Initialize(GameObject obj)
{
if (!obj.Initialized)
{
//Do something
obj.Initialized = true;
}
}
//Inside program that uses the framework
var player = new Player();
if (player.Initialized) //Compile-time error
Related
I'm trying to create my first bigger project in Unity and I am struggling to understand how abstract implementations away from the monobehaviour classes attached to gameobjects.
I am very familiar with dependency injection (using ASP.NET) but it seems DI is not a great idea to include in Unity projects according to a number of different articles. These articles say Unity has to handle Inversion of Control already, which is the Service Locator principal. I cannot find any built in implementation aside from methods like GameObject#Find or GameObject#GetComponent, etc.
An example would be a class handling interaction with files:
public interface IFileHandler { }
public class FileHandler : IFileHandler { }
public class FileHandling : MonoBehaviour
{
private IFileHandler fileHandler;
private void Awake()
{
this.fileHandler = new FileHandler();
}
}
Now the constructor of FileHandler changes. I would have to change it in every class.
How can I decouple the FileHandler from FileHandling?
Thanks in advance
I recall that in Asp.net there's Program.cs with main method that boots everything up. In unity you could have GameObject with similar Program.cs script that has been assigned a very low Script Execution Order. The script simply initialises your game systems if they have not been initialised yet.
During initialization you can create system instances and store to a static class like toolbox from where you can later reference them from anywhere. If your system needs to listen to unity events like update you can create a new GameObject with the script and set DontDestroyOnLoad enabled and store it to the Toolbox as well.
Toolbox is basically singleton for storing your other "singletons" so they don't have to be singletons. If you use interfaces you can easily swap out the implementation for the SaveSystem for example.
// Enum to allow multiple instances if needed
enum GameSystems { SaveSystem, GameManager }
public class GameTB {
//usage GameTB.toolBox.SetTool(GameSystems.SaveSystem, new SaveSystem());
public static ToolBox<GameSystems> toolBox = new ToolBox<GameSystems>();
//usage GameTB.SaveSystem.SaveGame();
public static ISaveSystem SaveSystem
{
get
{
return toolBox.GetTool<ISaveSystem>(GameSystems.SaveSystem);
}
}
public static IGameManager GameManager
{
get
{
return toolBox.GetTool<IGameManager>(GameSystems.GameManager);
}
}
}
public class ToolBox<T>
{
private Dictionary<T, object> Tools { get; } = new Dictionary<T, object>();
public K GetTool<K>(T key)
{
if (Tools.ContainsKey(key))
return (K)Tools[key];
else
return default(K);
}
public void SetTool(T key, object tool)
{
if (!Tools.ContainsKey(key))
Tools[key] = tool;
else
Tools.Add(key, tool);
}
public bool ContainsTool(T key)
{
if (Tools.ContainsKey(key) && Tools[key] != null)
return true;
else
return false;
}
public void ClearTools()
{
Tools.Clear();
}
}
I have a class for my acquisition device. Then I want to create another class that generates random samples for when my acquisition device is not connected.
This is my object:
private object AmplifierObj;
And I want a create it like that
if (AmpSettingsObj.DaqDevice == "noAmp")
AmpObj = new NoAmpManager(sampleRate: sampleRate);
else
AmpObj = new USBampManager(optCalibrationFlag: calibrationFlag,
serialNumbers: serialNumbers, sampleRate: sampleRate);
However, when I call one of the methods I get the error "object" does not contain a definition for the method . Both classes have exactly the same methods implemented. What would be the best way of implementing it? Should I use a generic class as a placeholder?
If both classes have the same methods you should have an interface (IAmplifier) and both classes should implement this interface.
This can be easily done by right clicking one of the classes and selecting Refactor / Extract Interface.
Assuming your interface name is IAmplifier, have both classes implement the same interface such as:
public class NoAmpManager : IAmplifier
{
... (Methods)
... (Properties)
}
public class USBampManager : IAmplifier
{
... (Methods)
... (Properties)
}
Then, instead of
private object AmplifierObj;
Use
private IAmplifier AmplifierObj;
You can do it like this
public class AmplifierObj
{
public Object AnySameProperty { get; set; }
}
public class NoAmpManager: AmplifierObj
{
public void Foo()
{
}
}
public class USBampManager : AmplifierObj
{
public void Bar()
{
}
}
But always must call the sub class property you should check object type
AmplifierObj AmpObj;
if (AmpSettingsObj.DaqDevice == "noAmp")
AmpObj = new NoAmpManager(sampleRate: sampleRate);
else
AmpObj = new USBampManager(optCalibrationFlag: calibrationFlag,
serialNumbers: serialNumbers, sampleRate: sampleRate);
if (AmpObj.GetType() == typeof(NoAmpManager))
((NoAmpManager)AmpObj).Foo();
else
((USBampManager)AmpObj).Bar();
I want instantiate complete class.
I have the Type of class which I want to instantiate.
Activator.createInstance(type) I created Instance.
I searched all field of this instance.
I have a field which is defined in another assembly so I load that and instantiate it.
Again I repeat step 3 and 4 for fields inside that class (nested)
I am creating an instance of every type
//in a1.dll
class class1
{
class2 var1;
//some Method
}
//in a2.dll
class class2
{
class3 var2;
//some Method
}
//in a3.dll
class class3
{
//some Method
}
I have to create instance of the entire class1 type.
So you want to create a class containing other classes.
Here is what you can do:
create a class instance through the Activator class
for each property and field type in the current instance, create a sub instance by calling the method you are in and assign the sub instance to the current instance field or property
The following code may help you start getting a handle on this problem, but please read it carefully, as well as the very important points under it:
public class A
{
public B MyBProperty { get; set; }
public C MyCField;
}
public class B
{
public C MyCField;
}
public class C
{
}
public class Creator
{
static MethodInfo mi;
static Creator()
{
mi = typeof(Creator).GetMethod("Create");
}
public T Create<T>()
{
var createdType = Activator.CreateInstance<T>();
// assign all properties
foreach (var p in typeof(T).GetProperties())
{
try
{
var mig = mi.MakeGenericMethod(p.PropertyType);
p.SetValue(createdType, mig.Invoke(this, null));
}
catch
{
}
}
// assign all fields
foreach (var f in typeof(T).GetFields())
{
try
{
var mig = mi.MakeGenericMethod(f.FieldType);
f.SetValue(createdType, mig.Invoke(this, null));
}
catch
{
}
}
return createdType;
}
}
// to use it:
var c = new Creator();
var a = c.Create<A>(); // should be instantiated
Now for some very important points:
this code is supposed to help you see how you can start, it is very naive
it doesn't check for infinite loops !!!
it doesn't cache any creation mechanisms
it fails if your class cannot be created, for example because it doesn't have a parameterless constructor
it fails silently
don't use it!
There are plenty of ways to automagically create objects, and this code is not a solid example, merely a starting point: if you want to know more, I would recommend reading the code from Autofixture or any other automatic object creation framework. I just hope it will help you look into the right direction.
If I have a class that is based off another class, how do I access the properties of the first class if it can have any name? I was thinking of using generics to access the properties, but the generics are "generic" for a reason...
For example:
public class AGameInXNA : Microsoft.Xna.Framework.Game
{
int ExampleGameProperty;
}
// ... another class ... //
public class ReferenceToAGameInXNA
{
Game gameInstance;
public void SetGameInstance(Game game)
{
gameInstance = game;
}
public void SetExampleGameProperty()
{
gameInstance.ExampleGameProperty = 21; // I don't know the name of
// AGameInXNA, so I want to
// access it using a generic
// class.
}
}
I know that that does not work, so how would I use generics in this case to access the AGameInXNA's properties in another class if I don't know AGameInXNA's name?
EDIT: I am trying to make it so that I can reuse this code later on. I want to be able to have a class that is unknown, such as public class unknownclassname that extends another class, such as Microsoft.Xna.Framework.Game, and be able to access the class unknownclassname without directly calling/implementing it in the library code.
I would recommend looking into XNA Services.
So for example, you would create a service which could be as simple as an
interface IExamplePropertyService
{
int ExampleProperty { get; set; }
}
public class AGameInXNA : Microsoft.Xna.Framework.Game, IExamplePropertyService
{
int ExampleGameProperty { get; set; }
void Initialize()
{
// Do other initialization
Services.Add( typeof(IExamplePropertyService), this );
}
}
public class ReferenceToAGameInXNA
{
IExamplePropertyService propertyService;
public void GetGameInstance(Game game)
{
propertyService = (IExamplePropertyService)game.GetService( typeof(IExamplePropertyService) );
}
public void SetExampleGameProperty()
{
propertyService.ExampleGameProperty = 21;
}
}
Implement it, and register it with the Game component, then in your ReferenceToAGameInXNA, you would query for this service and store it (rather than the Game) for use later.
As a bonus benefit, The IExamplePropertyService no longer even needs to be implemented by the Game class, it could be implemented by any GameComponent.
This makes for an easy way to seperate classes from having to know about the inner workings of other classes in the Game. So long as the services exist somewhere, your ReferenceToAGameInXNA can be used.
I don't think generics are what you are actually looking for here. In your second class, just change the type of all of the gameInstance to the type of the class you created for your game, in this case AGameInXNA. There should only be a need for one subclass of the Game type in each XNA game. That will allow you to access any public members of AGameInXNA from the Reference class.
If this isn't what you are after, please give a more detailed explanation of what you are trying to accomplish and I'll try to help you.
I don't know XNA, but if you want to have several classes that inherit from Game and have the same property on all of them, you could create an abstract class that inherits from Game and let the other classes inherit from that instead.
(Also, your GetGameInstance() is badly named, because it sets the field, it doesn't get it. And it's probably better as property anyway.)
public abstract class GameBase : Microsoft.Xna.Framework.Game
{
public int ExampleGameProperty { get; set; }
}
public class AGameInXNA : GameBase
{
// code specific to AGameInXNA
}
public class ReferenceToAGameInXNA
{
public GameBase GameInstance { get; set; }
public void SetExampleGameProperty()
{
GameInstance.ExampleGameProperty = 21;
}
}
If the other classed that have ExampleGameProperty shouldn't inherit from Game, you could create an interface instead. AGameInXNA would then inherit from Game directly and it would also implement the interface. And you would work with that interface in ReferenceToAGameInXNA.
using "Game gameInstance;" you can not acess ExmpleProp. You should use "AGameInXNA gameInstance;" too access ExampleProp.
I am programming a game as an exercise and I've run into a design problem. My role playing game will have the typical classes like Fighter, Wizard, Theif, Cleric. How do I design my classes so that players can multi-class? For example, one player might start off as a Fighter (and gain the related skills fighters have), then multi-class to a Wizard (at that point they gain wizard spells), and later on multi-class yet again to a rogue (now gaining all abilities rogues have). So this player is now a Fighter-Wizard-Rogue. I don't know to represent this in C#.
At first I tried to use the decorator pattern but I'm unable to multi-class multiple times with this. Any pointers on how to design this?
Only thing I can think of is having an IList<CharacterBaseClass> property for each character and adding Fighter, Wizard, Rogue, etc to this as the player multi-classes. So something like this..
class CharacterBaseClass
{
public IList<CharacterBaseClass> MultiClasses { get; set; }
// constructors, etc
}
and each time they mutli-class I add to the IList
// player starts off as Fighter
Warrior player1 = new Warrior();
// now multi-class to Wizard
player1.MultiClasses.Add(new Wizard());
// now multi-class to Theif
player1.MultiClasses.Add(new Theif());
I'm sure there must be a better way than this?
Just because your characters are wizards and warriors, that doesn't mean you have to create subclasses for them. Instead, ask yourself, "At the code level, what does a character's class do?" Likely, you won't want to have C# subclasses for character classes at all. Instead, figure out what the class actually does, and then determine the right way to model that in code.
For example, if character class restricts the equiment a character can use, then you can define a class for AllowedEquipment:
public class AllowedEquipment
{
public static AllowedEquiment Warrior()
{
return new AllowedEquipment() {
Daggers = true;
Swords = true;
Shields = true;
Armor = true
};
}
public static AllowedEquiment Wizard()
{
return new AllowedEquipment() {
Daggers = true;
Swords = false;
Shields = false;
Armor = true
};
}
public bool Daggers { get; set; }
public bool Swords { get; set; }
public bool Shields { get; set; }
public bool Armor { get; set; }
}
Don't feel you need to use subclasses to model every "is-a" relationship in your game.
Another option is to use the Type Object pattern to model your character classes. If you do that, it'd be easy to give each character a set of those Type Object instances instead of a single one, giving you, in effect, multiple inheritance.
With the decorator pattern, you could possibly do it.
Character person = new Character("Rambo");
person = new Fighter(person); // decorate him with Fighter skills
person = new Thief(person); // also decorate him with Thief skills
Personally I would probably look at attaching classes to the character instead:
Character person = new Character("Rambo");
person.AttachClass(new Fighter());
person.AttachClass(new Thief());
Of course, if you need complex interactions between the classes, so that not only does a Fighter/Thief gets bonuses and skills from each, but he gets something more as well, perhaps the only correct route for that might be to create specific multi-classes for all the combinations:
Character person = new Character("Rambo");
person.AttachClass(new FighterThief());
This would of course just explode with all the combinations.
What about a pure table-driven effort?
Place all applicable skills, spells, bonuses, effects, etc. in a hunking big table, then define the classes by linking a specific class to the specific items in that table. This way it would be much simpler to create hybrid classes by linking across different base classes.
To use a decorator pattern and still get proper access to everything, each class (in the programming sense of the word) needs to be implemented properly as a decorator class.
For instance:
public class BaseClass
{
protected BaseClass(BaseClass underlyingCharacterClass);
public abstract bool CanCastSpells();
public abstract List<Spell> GetAvailableSpells();
protected BaseClass UnderlyingCharacterClass;
}
public class Wizard : BaseClass
{
public override bool CanCastSpells() { return true; }
public override List<Spell> GetAvailableSpells()
{
List<Spell> result = new List<Spell>();
if (UnderlyingCharacterClass != null)
result.AddRange(UnderlyingCharacterClass.GetAvailableSpells());
result.Add(new WizardSpell1());
...
return result;
}
}
public class Thief : BaseClass
{
public override bool CanCastSpells()
{
if (UnderlyingCharacterClass != null)
return UnderlyingCharacterClass.CanCastSpells();
return false;
}
public override List<Spell> GetAvailableSpells()
{
List<Spell> result = new List<Spell>();
if (UnderlyingCharacterClass != null)
result.AddRange(UnderlyingCharacterClass.GetAvailableSpells());
return result;
}
}
If the classes have some common interface or base class, then multiclass is additional class (MultiClass) which also implements this interface or base class, then delegates to its contained instances.
For example:
public class MultiClass : Class {
...
public MultiClass(params Class[] classes) {
this.classes = classes;
}
public IEnumerable<Ability> GetAbilities() {
return this.classes.SelectMany(с => c.GetAbilities());
}
...
}
If you want to add more classes, you can add AddClass method to the base Class, which would create MultiClass from single class, or recreate multiclass with one more contained class for MultiClass.
Not everyone's cup of tea, but you could use state pattern.
public interface Player
{
void Fight();
void CastSpell();
void DoRoguishThings();
}
public class PlayerImpl : Player
{
Player fighter;
Player wizard;
Player rogue;
Player current;
public void Fight(){ current.Fight(); }
public void CastSpell(){ current.CastSpell(); }
public void DoRoguishThings(){ current.DoRoguishThings; }
public void MakeWizard(){ current = wizard; }
public void GoRogue(){ current = rogue; }
}
public class Fighter : Player
{
public void Fight(){ // do fighting }
public void CastSpell()
{
Console.WriteLine("You can't cast a spell, you are but a mere pugilist.");
}
...
}
public class Wizard : Player
{
public void Fight(){ // do wizardly fighting }
public void CastSpell() { // do spell-casting }
public void DoRoguishThings() { // whatever }
}
I think your characters should be able to have multiple Facet/Role implementing "Archetypes".
Then each one having multiple skills or attributes. Let's say...
class Archetype
{
string Name;
Dictionary<string,Type> Properties;
Dictionary<string,Action> Skills;
}
class Character
{
string Name;
string Alias;
Dictionary<Archetype,Dictionary<string,object>> FacetData;
}
class TheGame
{
public static void Main()
{
var Pilot = new Archetype();
Pilot.Name = "Combat-Pilot";
Pilot.Properties.Add("FlightHours", typeof(int));
Pilot.Properties.Add("AmbientTypes", typeof(List<string>));
var Jedi = new Archetype();
Jedi.Name = "Jedi";
Jedi.Properties.Add("ForceLevel", typeof(int));
Jedi.Properties.Add("Title", typeof(string));
Jedi.Properties.Add("IsCombatVeteran", typeof(bool));
Jedi.Skills.Add("LightSaberFight", FightWithLightSaber());
var Anakin = new Character();
Anakin.Id = 100;
Anakin.Name = "Anakin Skywalker";
Anakin.Alias = "Darth Vader";
Anakin.FacetData.Add(Pilot, new Dictionary<string, object>()
{ { "FlightHours", 2500 },
{ "AmbientTypes", new List<string>() {"Atmospheric", "Space", "Hyper-Space"} } };
Anakin.FacetData.Add(Jedi, new Dictionary<string, object>()
{ { "ForceLevel", 7 },
{ "Title", "Padawan" },
{ "IsCombatVeteran", true } };
Anakin.ApplySkill(Jedi, "LightSaberFight", Target);
}
public static void FightWithLightSaber(Character Target)
{
ShowBrightLightSaberPointingTo(Target);
EmitCoolSound();
}
}
If you get the Idea, then you could store properties/data and call skills/tasks with some degree of indirection and flexibility.
Good luck!
You may want to consider composition.
interface IWarrior
{
void Slash();
}
interface IMage
{
void Cast();
}
class Warrior : IWarrior
{
public void Slash() { }
}
class Mage : IMage
{
public void Cast() { }
}
class WarriorMage : IWarrior, IMage
{
private readonly Warrior _Warrior;
private readonly Mage _Mage;
public void Slash()
{
_Warrior.Slash();
}
public void Cast()
{
_Mage.Cast();
}
}
Néstor Sánchez A. provides you with a good solution. Drop your OOP thinking for a while and read this:
http://www.devmaster.net/articles/oo-game-design/
Not every problem can be solved with plain OOP in an elegant way.