在 C# 中,如何让一个对象的属性仅由该对象的组件修改?
How would I have properties of an object modified only by components of that object in C#?
假设我的游戏中有一个界面,IItem。 IItem 表示具有渲染组件、权重和附加 "process" 的对象。该过程可能由某人使用某种能力影响该项目来附加。也许类似于 RPG 中的 "enchantment"。假设我希望附加进程能够修改 IItem 的权重。但是,我只希望作为 IItem 组件的进程能够这样做。 IItem 之外的对象需要能够获得权重。
我是否在界面中仅使用 getter 来实现权重 属性?那么基础 class 是否实现了一个 "SetWeight" 方法,该方法在 Item 命名空间内部声明?当然,这仍然不能真正保证只有特定 IItem 拥有的组件才能影响它,但至少 Input 命名空间中的某些东西不能直接改变项目的权重。在 C 中,我可以做一些类似于内核中的链接列表的事情,它可以获得它们的容器,这将给我一种方法来确保权重和进程具有相同的容器对象,但是,我没有看到一个简单的方法来做到这一点在 C# 中。此外,我认为组件必须引用回其父组件会损害基于组件的设计。
这是我在设计界面和 classes 时 运行 遇到的一个普遍问题。
嗯,我想我明白你在说什么了。
确保您的过程,例如IEnchantment
可能将 IItem
作为依赖项(将其保留为成员),并使 IItem
具有采用 IEnchantment
的 Update/Set 方法,然后您可以检查,例如:
public void Update(IEnchantment enchantment)
{
if (enchantment.AttachedItem != this)
throw new Exception("Cannot Update Item!");
/*
* Execute Updating Logics
*/
}
Here's one library我尝试为自己的游戏设计,也许它可以帮助你思考一些事情。它远非完美,几乎什么都不是,但我希望它能以任何方式提供帮助。
您是否考虑过使用字典而不是属性?像这样:
// Item base class
public Dictionary<string, object> Attributes { get; private set; }
public List<Process> Enchantments { get; private set; }
public virtual T Get<T>(string identifier)
{
var att = this.Attributes.FirstOrDefault(att => att.Key == identifier);
if (att == null) throw new MissingAttributeExeption(identifier); // Or perhaps just return default(T)
if ((att.Value is T) == false) throw new InvalidAttributeCastException(identifier, typeof(T));
var value = att.Value;
foreach (var ench in this.Enchantments)
{
ench.Modify(identifier, ref value);
}
return value as T; // Maybe you need to cast value to Object, and then to T, I can't remember.
}
// Process class
public string ValueToModify { get; set }
public virtual void Modify(string identifier, ref object value)
{
if (identifier != this.ValueToModify) return;
// In an inherited class, for example a Weightless-Enchantment: Halfs all weight
var castedVal = value as int
value = castedVal / 2;
// Now this one item weights 50% of normal weight, and the original value is still stored in Item's Attributes dictionary.
}
// Some random class
public void Update()
{
var totalWeight = 0;
foreach (var item in this.itemCollection)
{
int weight = item.Get<int>("Weight");
totalWeight += weight;
}
Console.WriteLine("The player weights: {0}", totalWeight);
}
显然这意味着您不能真正对属性进行硬编码,但是...您真的想这样做吗,在漫长的 运行 中?我的意思是一旦你开始增加智力、敏捷、力量、耐力、耐力等
我知道这不能解决您提出的问题,但我认为这是一个相当不错的选择。
假设我的游戏中有一个界面,IItem。 IItem 表示具有渲染组件、权重和附加 "process" 的对象。该过程可能由某人使用某种能力影响该项目来附加。也许类似于 RPG 中的 "enchantment"。假设我希望附加进程能够修改 IItem 的权重。但是,我只希望作为 IItem 组件的进程能够这样做。 IItem 之外的对象需要能够获得权重。
我是否在界面中仅使用 getter 来实现权重 属性?那么基础 class 是否实现了一个 "SetWeight" 方法,该方法在 Item 命名空间内部声明?当然,这仍然不能真正保证只有特定 IItem 拥有的组件才能影响它,但至少 Input 命名空间中的某些东西不能直接改变项目的权重。在 C 中,我可以做一些类似于内核中的链接列表的事情,它可以获得它们的容器,这将给我一种方法来确保权重和进程具有相同的容器对象,但是,我没有看到一个简单的方法来做到这一点在 C# 中。此外,我认为组件必须引用回其父组件会损害基于组件的设计。
这是我在设计界面和 classes 时 运行 遇到的一个普遍问题。
嗯,我想我明白你在说什么了。
确保您的过程,例如IEnchantment
可能将 IItem
作为依赖项(将其保留为成员),并使 IItem
具有采用 IEnchantment
的 Update/Set 方法,然后您可以检查,例如:
public void Update(IEnchantment enchantment)
{
if (enchantment.AttachedItem != this)
throw new Exception("Cannot Update Item!");
/*
* Execute Updating Logics
*/
}
Here's one library我尝试为自己的游戏设计,也许它可以帮助你思考一些事情。它远非完美,几乎什么都不是,但我希望它能以任何方式提供帮助。
您是否考虑过使用字典而不是属性?像这样:
// Item base class
public Dictionary<string, object> Attributes { get; private set; }
public List<Process> Enchantments { get; private set; }
public virtual T Get<T>(string identifier)
{
var att = this.Attributes.FirstOrDefault(att => att.Key == identifier);
if (att == null) throw new MissingAttributeExeption(identifier); // Or perhaps just return default(T)
if ((att.Value is T) == false) throw new InvalidAttributeCastException(identifier, typeof(T));
var value = att.Value;
foreach (var ench in this.Enchantments)
{
ench.Modify(identifier, ref value);
}
return value as T; // Maybe you need to cast value to Object, and then to T, I can't remember.
}
// Process class
public string ValueToModify { get; set }
public virtual void Modify(string identifier, ref object value)
{
if (identifier != this.ValueToModify) return;
// In an inherited class, for example a Weightless-Enchantment: Halfs all weight
var castedVal = value as int
value = castedVal / 2;
// Now this one item weights 50% of normal weight, and the original value is still stored in Item's Attributes dictionary.
}
// Some random class
public void Update()
{
var totalWeight = 0;
foreach (var item in this.itemCollection)
{
int weight = item.Get<int>("Weight");
totalWeight += weight;
}
Console.WriteLine("The player weights: {0}", totalWeight);
}
显然这意味着您不能真正对属性进行硬编码,但是...您真的想这样做吗,在漫长的 运行 中?我的意思是一旦你开始增加智力、敏捷、力量、耐力、耐力等
我知道这不能解决您提出的问题,但我认为这是一个相当不错的选择。