我使用的是ECS架构,其中abstractcomponent类的组件仅使用值类型,而 never 引用类型。我希望base abstractcomponent类包含1和1个shallowcopy方法,而不必为每个具体类重新实现。
任何想法? C#?
/// <summary>
/// Only an empty classification/tag class. (Every last component is POD -- no exceptions!)
/// </summary>
public abstract class AbstractComponent
{
public T CreateShallowClone(AbstractComponent c) where T : AbstractComponent
{
return (T)c.MemberwiseClone();
}
}
[Serializable]
public sealed class Entity : Identifiable
{
public Entity() : base()
{
}
public bool IsEnabled { get; set; } = false;
private Dictionary<Type, AbstractComponent> Components { get; set; } = new Dictionary<Type, AbstractComponent>();
public void AddComponent(AbstractComponent c)
{
Components.Add(c.GetType(), c);
}
public void RemoveComponent<T>() where T : AbstractComponent<T>
{
if (!Components.Remove(typeof(T))) {
throw new KeyNotFoundException();
}
}
public bool HasComponent<T>() where T : AbstractComponent<T>
{
if (Components.ContainsKey(typeof(T)))
{
return true;
}
else
{
return false;
}
}
public T GetComponent<T>() where T : AbstractComponent<T>
{
AbstractComponent<T> c;
if (!Components.TryGetValue(typeof(T), out c))
{
throw new KeyNotFoundException();
}
return c as T;
}
public void Destroy()
{
Components = null;
}
}
答案 0 :(得分:1)
如果我理解正确,你可以这样使用泛型。
public abstarct class AbstractComponent<TFinalComponent> where TFinalComponent : AbstractComponent<TFinalComponent> {
public TFinalComponent CreateShallowClone() {
return (TFinalComponent)this.MemberwiseClone();
}
}
修改强> 现在我终于从源代码中看到了这一点。 泛型是不必要的。一切都可以在没有它们的情况下完成。
public abstract class AbstractComponent {
public AbstractComponent CreateShallowClone() {
return (AbstractComponent)this.CreateShallowClone();
}
}
public sealed class MyCustomComponent : AbstractComponent {
public string Name { get; set; }
public int Age { get; set; }
}
public sealed class Entity {
public bool IsEnabled { get; set; }
private Dictionary<Type, AbstractComponent> components = new Dictionary<Type, AbstractComponent>();
public void AddComponent(AbstractComponent component) {
if (null == component) { throw new ArgumentNullException("component"); }
this.components.Add(component.GetType(), component);
}
public bool RemoveComponent(Type componentType) {
if (null == componentType) { throw new ArgumentNullException("componentType"); }
return this.components.Remove(componentType);
}
public bool HasComponent(Type componentType) {
if (null == componentType) { throw new ArgumentNullException("componentType"); }
return this.components.ContainsKey(componentType);
}
public AbstractComponent FindComponent(Type componentType) {
if (null == componentType) { throw new ArgumentNullException("componentType"); }
AbstractComponent result;
this.components.TryGetValue(componentType, out result);
return result;
}
public AbstractComponent GetComponent(Type componentType) {
if (null == componentType) { throw new ArgumentNullException("componentType"); }
var result = this.FindComponent(componentType);
if (null == result) {
throw new ArgumentException("The component of the specified type was not found.", "componentType");
}
return result;
}
public TComponent GetComponent<TComponent>() where TComponent : AbstractComponent {
return (TComponent)this.GetComponent(typeof(TComponent));
}
public void Destroy() {
this.components.Clear();
}
public Entity Clone() {
var result = new Entity();
foreach (var item in this.components.Values) {
var clonedItem = item.CreateShallowClone();
result.AddComponent(item);
}
return result;
}
}
一些注意事项:
RemoveComponent()
不需要泛型,通常使用非泛型方法(如果可以选择)更好,因为调用者在编译时不需要知道具体类型RemoveComponent()
不需要抛出异常。对于这两种情况,结果都是相同的 - 组件将不存在于实体中FindComponent()
可以用来代替调用HasComponent()
和GetComponent
。对于perfofmance来说,它更好。方法GetComponent()
已超载
RemoveComponent()
方法相同。var custom = entity.GetComponent();