如何在C#中仅使用该对象的组件修改对象的属性?

时间:2015-12-05 22:28:16

标签: c# oop design-patterns monogame

所以,让我说我的游戏中有一个界面,IItem。 IItem表示一个具有渲染组件,权重和附加过程的对象"。某人可能会使用某种能力影响该项目来附加该过程。也许就像一个"结界"在RPG中。让我们说我希望这个附加过程能够修改IItem的权重。但是,我只想要一个能够完成IItem组件的进程。 IItem之外的物体需要能够获得重量。

我是否实现了Weight属性,界面中只有一个getter?然后基类实现" SetWeight"方法,在Item命名空间内部声明?这仍然不能保证只有特定IItem拥有的组件当然会影响它,但至少Input项中的某些东西不能直接改变项的权重。在CI中可以做一些类似于内核中可以获取容器的链表,这会给我一种方法来确保权重和进程具有相同的容器对象,但是,我没有看到一个简单的方法来做到这一点在C#中。此外,我认为这会损害组件的基于组件的设计,以便必须将引用返回给其父组件。

这是我在设计界面和类时遇到的一般问题。

2 个答案:

答案 0 :(得分:1)

好吧,我想我得到了你正在谈论的内容。

确保您的流程,例如IEnchantment可能会将IItem作为依赖项(将其保留为成员),并使IItem具有采用IEnchantment的更新/设置方法,然后您可以检查那,例如:

public void Update(IEnchantment enchantment)
{
    if (enchantment.AttachedItem != this)
        throw new Exception("Cannot Update Item!");
    /*
     * Execute Updating Logics
     */
}

Here's one library我尝试过为自己的游戏设计,也许它可以帮助你思考一些事情。它远非完美,它几乎没有任何东西,但我希望它能以任何方式提供帮助。

答案 1 :(得分:1)

您是否考虑使用词典而不是属性?像这样:

// 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);
}

显然这意味着你不能真正硬编码属性,但是......从长远来看,你是否真的想要这样做呢?我的意思是,一旦你开始添加智力,敏捷,力量,耐力,耐力等等。

我知道这并没有解决你提出的问题,但我认为这是一个相当不错的选择。