Question

I am writing a dialog module for my XNA game as a learning project. I have been using the accepted answer here as a guide.

Every ILink contains an ICollection<ICondition>, which is used to determine whether or not all conditions have been met in order to make a particular dialog link appear as an option:

public interface INode
{
    int ID { get; set; }
    ICollection<ILink> Links { get; set; }
}

public interface ILink
{
    INode Target { get; set; }
    IScript Script { get; set; }
    ICollection<string> Text { get; set; }
    ICollection<ICondition> Conditions { get; set; }
}

public interface IScript { void Execute(); }
public interface ICondition { bool Evaluate(); }

Based on this, it was apparent that each type of comparison I wanted to make would have to be its own class:

public class EntityHasItem : ICondition
{
    public IEntity Entity { get; set; }
    public IItem Item { get; set; }
    public bool Evaluate() { return Entity.Inventory.Contains(Item); }
}

Or

public class QuestHasFlag : ICondition
{
    public IQuest Quest { get; set; }
    public IFlag Flag { get; set; }
    public bool Evaluate() { return Quest.Flags.Contains(Flag); }
}

How can I check what type each element of INode.Conditions is? I might make an editor, or provide feedback, for example. Because of the generic collection, it will always return with ICondition (which is the most common derived type), but it only exposes Evaluate(), which isn't much help here.

My first thought was to use reflection to get a list of types that were derived from ICondition, then compare that list against every element of the collection, but that seems like overkill. Is there a better way?

Was it helpful?

Solution

You shouldn't need to do this, violation of an interface (by downcasting) should only be done with great care and good reason.

There are two use cases you mentioned for wanting to do this, viewing and editing.

For viewing, the solution is simple. Either override .ToString() to get the information you need, or if you need "pretty" output, create an interface function DrawInfo to do this display for you (passing parameters as necessary, like an area of the screen to draw to).

For editing, you'll want a DrawDialog function. Like the DrawInfo function, this could take an "area" parameter. Assuming this dialog can manage its own UI controls (buttons and the like) you're done. This, by the way, would be analogous to having a class return a UserControl in WPF/Winforms to do the same thing.

Having these in the interface ensures that every derived class has it (invoking a method via reflection is not safe or fun!) and you don't need to worry about the types at runtime, polymorphism takes care of everything for you.

OTHER TIPS

you can call the GetType() method on any .NET object. This will return the actual type of the object (EntityHasItem, QuestHasFlag, etc).

http://msdn.microsoft.com/en-us/library/system.object.gettype.aspx

for example:

foreach(var condition in type.Conditions)
{
   Debug.WriteLine(condition.GetType().FullName);
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top