ArXen42
@ArXen42

Как обойти ограничение на отсутствие параметров у конструктора класса generic типа?

Здравствуйте. Пишу небольшой учебный рейтрейсер, хочу организовать в нем компонентно-ориентированную модель, подобную используемой в unity3d. Столкнулся с проблемой:
Есть класс Component. Он прост как топор:
public class Component
{
	private Component(){}
	
	public Component(SceneObject ownerSceneObject)
	{
		this.ownerSceneObject = ownerSceneObject;
	}
	public readonly SceneObject ownerSceneObject;
}

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

И вот тот самый метод в SceneObject:
public void AddComponent<ComponentType>() where ComponentType:Component, new(SceneObject ownerSceneObject)
	{
		components.Add(new ComponentType(this));
	}


И все бы хорошо, но компилятор не разрешает мне такое сделать - нельзя задать ограничение конструктора с параметрами, только без - просто new(). В итоге я не могу вызвать конструктор добавляемого компонента, что вываливается в null reference exception (т.к. не был вызван конструктор производного от Component класса).
Как обойти это ограничение?

Иными словами: как можно заставить generic метод вызывать конструктор с параметрами этого самого generic класса (в смысле класса, имеющего тип generic)?
  • Вопрос задан
  • 507 просмотров
Пригласить эксперта
Ответы на вопрос 2
@MonkAlex
C#, SQL, Delphi, C++ etc
Сама идея такой зависимости мне не нравится, но понять ЗАЧЕМ - я не могу.
public class Component
  {
    public Component(SceneObject ownerSceneObject)
    {
      this.ownerSceneObject = ownerSceneObject;
    }
    public readonly SceneObject ownerSceneObject;
  }

  public class SceneObject
  {
    private List<Component> components;
     
    public void AddComponent<T>() where T : Component
    {
      var constructor = typeof(T).GetConstructor(new [] { typeof(SceneObject) });
      var created = constructor.Invoke(new object[] { this }) as T;
      if (created != null)
        this.components.Add(created);
    }

    public SceneObject()
    {
      this.components = new List<Component>();
    }
  }
  }
Ответ написан
Vestail
@Vestail
Software Engineer
Можете так попробовать.
public class SceneObject 
{
    //.....
    
    public void AddComponent<ComponentType>(Func<SceneObject, ComponentType> inst) where ComponentType : Component
    {
        components.Add(inst(this));
    }
    
    public static void Main(string[] args)
    {
        SceneObject sObj = new SceneObject();
        sObj.AddComponent((a) => new Component(a) );
      
    }
}
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы