2010-07-21 3 views
1

Я пытаюсь выяснить систему, которая может легко изменять объекты «на лету».Modifier System C#

вот пример. Допустим, у меня есть Entity2D, который наследуется от Entity. Entity2D имеет свойство Position.

Теперь у меня есть класс ModifyPosition, который наследуется от модификатора.

Вот код

public class Entity 
{ 
/// <summary> 
/// Applies the modifier to this entity. 
/// </summary> 
/// <param name="modifier">The modifier to apply.</param> 
public void ApplyModifier(Modifier modifier) 
{ 
    modifier.Apply(this); 
} 
} 

/// <summary> 
/// Modifies an entities position 
/// </summary> 
public class ModifyPosition : Modifier 
{ 
    /// <summary> 
    /// Initializes a new instance of the <see cref="ChangePosition"/> class. 
    /// </summary> 
    /// <param name="position">The position.</param> 
    public ChangePosition(Vector2 position) 
    { 
     this.Position = position; 
     this.IsModifyingChildren = false; 
    } 

    /// <summary> 
    /// Gets the position. 
    /// </summary> 
    /// <value>The position.</value> 
    public Vector2 Position { get; private set; } 

    /// <summary> 
    /// Applies this change to the specified entity. 
    /// </summary> 
    /// <param name="entity">The entity.</param> 
    internal override void Apply(Entity entity) 
    { 
     ((Entity2D)entity).X += this.Position.X; 
     ((Entity2D)entity).Y += this.Position.Y; 
    } 
} 

Но если вы вызываете это несколько раз в секунду, я думаю, что отливка бы замедлить его.

Есть ли другой способ обойти это без необходимости бросать?

+0

что вы сделали, удалите и перепросите вопрос? Не лучший способ получить ответы –

+1

Возможно, странно, что объект появился и изменил объект снаружи (и, возможно, нарушил несколько рекомендаций). Есть ли какая-то причина, по которой вам нужно это делать, в отличие от внутреннего кода модификации объекта? –

+0

@ Лукас это был приятель ... = /, и я не получил, чтобы прочитать ответы, которые были опубликованы, поэтому я попытался спросить об этом ... извините. Вы ответили раньше? не возражаете ли вы повторить ответ? снова жаль, что это была моя ошибка. @silky Я думал, что если бы у меня был способ изменить объект снаружи, это облегчило бы возможность изменять свойства объекта на лету, как в редакторе. –

ответ

1

, если вы используете интерфейс IEntity

interface IEntity 
{ 
double X{get;} 
double Y{get;} 
} 

есть Entity реализовать этот интерфейс

public class Entity: IEntity 
{ 
... 
} 

и использовать его в качестве параметра типа для Нанести

internal override void Apply(IEntity entity) 
    { 
     entity.X += this.Position.X; 
     entity.Y += this.Position.Y; 
    } 

тогда вы не должны быть отлиты

0

С C# вы должны убедиться, что тип, который вы изменяете, поддерживает вашу модификацию (не соответствует действительности на некоторых языках). Поэтому ваши модификаторы должны будут четко знать, какие типы они изменяют. (Альтернативно, ваши сущности могут знать об модификаторах, но представляется более разумным дать модификаторам знания.)

На данный момент у меня нет ответа для вас; это моя попытка, но я получаю ошибку компилятора в объявлении ModifyPosition.Apply, заявляя, что вы не можете указать ограничения типа для реализации переопределенного метода.

public interface IPositionableEntity 
{ 
    Vector2 Position { get; set; } 
} 

public class Entity 
{ 
    public void ApplyModifier<T>(T modifier) where T : Modifier 
    { 
     modifier.Apply(this); 
    } 
} 

public class Entity2D : Entity, IPositionableEntity 
{ 
    public Vector2 Position { get; set; } 
} 

public class Vector2 
{ 
    public double X { get; set; } 
    public double Y { get; set; } 
} 

public abstract class Modifier 
{ 
    public abstract void Apply<T>(T entity); 
} 

public class ModifyPosition : Modifier 
{ 
    public ModifyPosition(Vector2 position) 
    { 
     Position = position; 
    } 

    public Vector2 Position { get; private set; } 

    //Compiler error here: 
    //Constraints for explicit interface implementation method are inherited 
    //from the base method, so they cannot be specified directly 
    public override void Apply<T>(T entity) where T : IPositionableEntity 
    { 
     entity.Position.X += Position.X; 
     entity.Position.Y += Position.Y; 
    } 
} 

EDIT - Вот один, что, по крайней мере компилирует. Единственное изменение - ModifyPosition.

public class ModifyPosition : Modifier 
{ 
    public ModifyPosition(Vector2 position) 
    { 
     Position = position; 
    } 

    public Vector2 Position { get; private set; } 

    public override void Apply(object entity) 
    { 
     if (!(entity is IPositionableEntity)) 
     { 
      return; //throw, whatever 
     } 

     var positionableEntity = (IPositionableEntity) entity; 
     positionableEntity.Position.X += Position.X; 
     positionableEntity.Position.Y += Position.Y; 
    } 
} 
+0

Интересно, это может сработать, но он может получить анонимность, чтобы иметь много интерфейсов, связанных с классом, когда он начинает иметь много свойств, которые вы хотите изменить. –

+0

См. Мой комментарий к вашему вопросу. Я не думаю, что это будет возможно решить эту проблему как обычно, как вы хотите на C#. – arootbeer

+0

Ваше редактирование не поможет вам снова бросать. –

0

Попробуйте что-то вроде этого:

class CatEntity : Entity, IModifiablePosition 
{ 
    // Interface method 
    public void ModifyPosition(Vector2 blah) { ... } 
... 
} 


class RobotEntity : Entity, IModifiableShader, IModifiablePosition 
{ 
// Interface method 
public void PushShader(RobotEffect bleh) { ... } 
public void ModifyPosition(Matrix blah) { ... } 
... 
} 

class ShaderModifier : IModifier 
{ 
    public override void Apply(IModifiableShader obj) 
    { 
    obj.PushShader(m_furryEffect); 
    } 
} 

class PositionModifier : IModifier 
{ 
    public override void Apply(IModifiablePosition obj) 
    { 
    obj.ModifyPosition(m_mxTranslation); 
    } 
} 

Это кажется легко читаемым и безопасно - надеюсь, что это работает для тебя.