简体   繁体   English

修改器系统C#

[英]Modifier System C#

I am trying to figure out a system that can easily modify objects on the fly. 我正在尝试找出一个可以轻松动态修改对象的系统。

here is an example, Lets say I have an Entity2D that inherits from Entity. 这是一个示例,假设我有一个从Entity继承的Entity2D。 Entity2D has a Position property. Entity2D具有Position属性。

Now I have a class called ModifyPosition that inherits from Modifier. 现在,我有一个名为ModifyPosition的类,该类继承自Modifier。

Here is some code 这是一些代码

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

But if you are calling this multiple times per second I would think that the casting would slow it down. 但是,如果您每秒调用多次,我会认为转换会降低速度。

Is there another way to go about this without having to cast? 是否有另一种方法可以不必强制转换?

if you use an interface IEntity 如果您使用接口IEntity

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

have Entity implement that interface 让实体实现该接口

public class Entity: IEntity
{
...
}

and use that as the parameter type for Apply 并将其用作Apply的参数类型

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

then you don't have to cast 那你就不用投

With C# you have to ensure that the type you're modifying supports your modification (not true with some languages). 使用C#,您必须确保您要修改的类型支持您的修改(某些语言不适用)。 So your modifiers will have to know explicitly which types they're modifying. 因此,您的修饰符将必须明确知道它们正在修饰的类型。 (Alternately your entities could know about the modifiers, but it seems more reasonable to give the modifiers the knowledge.) (或者,您的实体可以知道修饰符,但为修饰符提供知识似乎更合理。)

I don't actually have an answer for you at this point; 在这一点上,我实际上还没有答案。 this is my attempt, but I get a compiler error in the ModifyPosition.Apply declaration stating that you cannot specify type constraints on an overridden method implementation. 这是我的尝试,但是在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 - Here's one that at least compiles. 编辑 -这是至少可以编译的一个。 The only change is to ModifyPosition. 唯一的更改是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;
    }
}

Try something like this: 尝试这样的事情:

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

This seems easily readable and safe -- hope it works for ya. 这似乎很容易理解和安全-希望它对您有用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM