[英]Having a master clone method in an abstract class
I am using an ECS architecture where components of the abstractcomponent class use value types only, and never reference types. 我使用的是ECS架构,其中的abstractcomponent类使用价值种成分而已, 从来没有引用类型。 I would like for the base abstractcomponent class to contain 1 and 1 shallowcopy method without having to reimplement that for each individual concrete class.
我希望基本abstractcomponent类包含1和1浅表复制方法,而不必为每个具体的类重新实现。
ANy ideas? 有任何想法吗? C#?
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;
}
}
If I understand right, you can use generics this way. 如果我理解正确,则可以通过这种方式使用泛型。
public abstarct class AbstractComponent<TFinalComponent> where TFinalComponent : AbstractComponent<TFinalComponent> {
public TFinalComponent CreateShallowClone() {
return (TFinalComponent)this.MemberwiseClone();
}
}
EDIT: Now I finally see the point from your source code. 编辑:现在,我终于从您的源代码中看到了重点。 The generics are unnecessary.
泛型是不必要的。 All can be done without them.
没有他们,所有事情都可以完成。
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;
}
}
Some notes: 一些注意事项:
RemoveComponent()
does not need generics, generaly it's better to have non-generic methods (if you can choose) because caller does not need know concrete type before compile-time RemoveComponent()
不需要泛型,通常最好有非泛型方法(如果可以选择),因为调用者在编译时不需要知道具体类型 RemoveComponent()
does not need throw exception when component was not present. RemoveComponent()
不需要引发异常。 the result will be same for both cases - the component will be not present in the entity FindComponent()
can be used instead of calling HasComponent()
and GetComponent
. FindComponent()
代替调用HasComponent()
和GetComponent
。 it's better for perfofmance. method GetComponent()
is overloaded 方法
GetComponent()
已重载
RemoveComponent()
method. RemoveComponent()
方法。 var custom = entity.GetComponent(); var custom = entity.GetComponent();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.