C# 如何向类添加可选功能?

C# 如何向类添加可选功能?,c#,xna,C#,Xna,我目前正在尝试学习XNA/C的细节,但我目前遇到了一个问题:我想向类添加可选功能,但我甚至不知道如何开始。为清楚起见,以下是我当前的代码: public class Actor { //Fields private Vector3 m_location; //Properties public Vector3 Location { get { return m_location; } set { m_location =

我目前正在尝试学习XNA/C的细节,但我目前遇到了一个问题:我想向类添加可选功能,但我甚至不知道如何开始。为清楚起见,以下是我当前的代码:

public class Actor
{
    //Fields
    private Vector3 m_location;

    //Properties
    public Vector3 Location
    {
        get { return m_location; }
        set { m_location = value; }
    }

    //Constructors
    public Actor(float x, float y, float z)
    {
        Location = new Vector3(x, y, z);
    }
    public Actor(Vector3 location)
    {
        Location = location;
    }
}

public class Actor2D : Actor
{
    //Fields
    private Texture2D m_texture;

    //Properties
    public Texture2D Texture
    {
        get { return m_texture; }
        set { m_texture = value; }
    }

    //Constructors
    public Actor2D(float x, float y, float z) : base(x, y, z) {}
    public Actor2D(Vector3 vector) : base(vector) {}

    //Methods
    public void Draw(SpriteBatch spriteBatch)
    {
        spriteBatch.Draw(Texture, new Vector2(Location.X, Location.Y), Color.White);
    }
    public void Load(ContentManager content, string asset)
    {
        Texture = content.Load<Texture2D>(asset);
    }
}
公共类参与者
{
//田地
专用矢量器3 m_位置;
//性质
公共矢量3位置
{
获取{return m_location;}
设置{m_location=value;}
}
//建设者
公共参与者(浮动x、浮动y、浮动z)
{
位置=新矢量3(x,y,z);
}
公共参与者(矢量3位置)
{
位置=位置;
}
}
公共类Actor 2d:Actor
{
//田地
私有纹理2D m_纹理;
//性质
公共纹理2D纹理
{
获取{return m_texture;}
设置{m_texture=value;}
}
//建设者
公共Actor2D(float x,float y,float z):基(x,y,z){}
公共Actor2D(Vector3向量):基(向量){}
//方法
公共作废抽签(SpriteBatch SpriteBatch)
{
绘制(纹理,新矢量2(Location.X,Location.Y),颜色,白色);
}
公共无效加载(ContentManager内容、字符串资源)
{
纹理=内容。加载(资源);
}
}

这里的逻辑是,所有演员都必须有一个位置,但他们不一定要有纹理,因为演员可以是光源、触发器等。Actor2D在这方面类似,只是它被指定为使用2D纹理的演员。我想做的是能够根据需要向这些类中的任何一个添加功能。假设我想让Actor2D动画化,或者像前面提到的那样,我想给一个无背景的演员添加一个触发器或光源。。。有什么想法可以帮助我实现这些目标?

你可以试着看一下,它允许你“附加”对象的行为。

如果你真的想让对象“变形”,比如在运行时改变对象的方法集,你可以看看。(教程)
公平警告:这不是给胆小鬼的

现在,由于在编译时您知道所有必须可用的类型,因此可以使用多种接口:

  • IHasTexture
  • IDrawable:IHasTexture(这意味着IDrawable必须自动实现IHasTexture,因为您无法以其他方式绘制)
  • 我可以
  • 。。。你要多少就多少
然后为您需要的每个组合提供一个实现。此外,我认为最好将所有这些放在您的业务层(如果您有)

希望这有帮助

巴布

编辑:示例

public interface IMovable { void Move(); }

public class MoveMixin : IMovable
{
   public void Move() { Console.WriteLine("I am moving"); }
}

public class SomeDude { }

public static class TestClass
{
   public static Test()
   {
      var myMixinConfiguration = MixinConfiguration.BuildFromActive()
           .ForClass<SomeDude>().AddMixin<MoveMixin>()
           .BuildConfiguration();
      using(myMixinConfiguration.EnterScope())
      {//In this scope, SomeDude implements IMovable, but only if you get an instance through the ObjectFactory
         var myMovableDude = ObjectFactory.Create<SomeDude>(ParamList.Empty);
         ((IMovable)myMovableDude).Move(); //This line compiles and executes just fine, even though the class declaration does not specify anything about Move() !!
      }
      //The SomeDude class no longer implements IMovable
   }
}
公共接口IMovable{void Move();}
公共类MoveMixin:iMoved
{
public void Move(){Console.WriteLine(“我正在移动”);}
}
公共类SomeDude{}
公共静态类TestClass
{
公共静态测试()
{
var myMixinConfiguration=MixinConfiguration.BuildFromActive()
.ForClass().AddMixin()文件
.BuildConfiguration();
使用(myMixinConfiguration.EnterScope())
{//在此范围内,SomeDude实现了IMovable,但前提是您通过ObjectFactory获得一个实例
var mymovableddude=ObjectFactory.Create(ParamList.Empty);
((IMovable)myMovableDude).Move();//这一行编译和执行得很好,即使类声明没有指定关于Move()的任何内容!!
}
//SomeDude类不再实现iMoved
}
}

而不是使
Actor2D
(及其类似内容)派生自
Actor
。只需将这些派生类更改为它们自己的类,并为每个具有所有这些属性的“Actor”创建一个类(
Actor
)。(一个
Actor2D
属性…)然后在运行时使用您需要的任何属性

它们不会占用那么多资源,因为它们在不使用时将指向
null

编辑:

然后像这样使用它:

Actor actor1 = new Actor();

//First it's going to be a 2D.
actor1.stuff2d.weight = 3;
//...

//Now it's changed to a light source.
actor1.stuff2d = null;
actor1.lightPower.color = Color.White;
//...

//And back again.
actor1.lightPower = null;
actor1.stuff2d = new Stuff2D();
//...

因此,在Google/StackOverflow上进行了一系列思考和搜索之后。我终于找到了答案。我学到了应该使用更面向组件的编程方法,而不是使用传统的OOP方法。我在基于组件的游戏引擎设计中发现了一个非常好的链接


特别令人感兴趣的是关于T=Machine的5部分系列,它描述了实体系统,这似乎是一种完全符合我所寻找的方法。对于那些感兴趣的人,第一个帖子是:。

谢谢你的快速回答。我很抱歉没有说得那么清楚。我当然希望能够“附加”特性,但我不想使用继承或接口,因为我希望类尽可能基本,每次我想向类添加特定的“功能”时,我都必须重新编译。我真的很想在运行时“抓住”这些特性。谢谢你,宝贝,但我真的在努力避免任何外部库,这仍然不是我想要的(尽管很接近)。我希望事情尽可能干净,我想成为一名演员。我同意所有Actor2D都有“Animate()”方法,但我不希望该方法所需的字段/属性存储在类中,因为这会浪费不必要的资源。mixin允许您定义接口的默认实现,并在运行时动态注入该代码。您的对象仍然可以像它们自己一样强制转换,它们只是获取了一个额外的接口实现。代码完全设置在另一个类(称为“Mixin”)中。在我看来,这就是你想要的。对不起,我试图通读文档和示例,看起来我仍然必须声明say-Actor2D:IAnimated才能定义动画的功能。这很有意义,因为游戏需要知道如何准确地在Actor2D上执行动画。我想我只是不太明白发生了什么
Actor actor1 = new Actor();

//First it's going to be a 2D.
actor1.stuff2d.weight = 3;
//...

//Now it's changed to a light source.
actor1.stuff2d = null;
actor1.lightPower.color = Color.White;
//...

//And back again.
actor1.lightPower = null;
actor1.stuff2d = new Stuff2D();
//...