Frage

Es ist komisch, dass dies das erste Mal, dass ich in dieses Problem gestoßen habe, aber:

Wie definieren Sie einen Konstruktor in einer C # Schnittstelle?

Bearbeiten
Einige Leute wollten ein Beispiel (es ist ein Freizeit-Projekt, also ja, es ist ein Spiel)

IDrawable
 + Update
 + Draw

Um in der Lage sein, zu aktualisieren (Prüfung auf Rand des Bildschirms usw.) und zeichnen sich wird es immer brauchen eine GraphicsDeviceManager. Deshalb möchte ich sicherstellen, dass das Objekt einen Verweis auf sie hat. Dies würde im Konstruktor gehört.

Nun, da ich diese aufschrieb denke ich, was ich Umsetzung hier ist IObservable und die GraphicsDeviceManager sollte die IDrawable nehmen ... Es scheint, entweder ich nicht XNA Framework erhalten, oder der Rahmen ist nicht sehr gut durchdacht.

Bearbeiten
Es scheint im Zusammenhang mit einer Schnittstelle einige Verwirrung über meine Definition von Konstruktor zu sein. Eine Schnittstelle kann in der Tat nicht so braucht keinen Konstruktor instanziiert werden. Was ich wollte, eine Signatur an einen Konstruktor definieren war. Genau wie eine Schnittstelle eine Signatur einer bestimmten Methode definieren, wobei die Schnittstelle die Unterzeichnung eines Konstruktor definieren könnte.

War es hilfreich?

Lösung

Wie bereits gut erwähnt, können Sie nicht auf eine Schnittstelle haben Konstrukteure. Da aber das ist so ein hoch bewertetes Ergebnis in Google später einig 7 Jahren, dachte ich, dass ich hier Chip würde - speziell zeigen, wie man eine abstrakte Basisklasse im Tandem mit Ihrer vorhandenen Schnittstelle verwenden könnte und vielleicht reduziert auf die Menge an Refactoring in Zukunft für ähnliche Situationen benötigt. Dieses Konzept hat sich bereits in einigen Kommentaren angedeutet, aber ich dachte, es würde sich lohnen zeigt, wie man es eigentlich zu tun.

So können Sie Ihre Haupt-Schnittstelle haben, die so aussieht, so weit:

public interface IDrawable
{
    void Update();
    void Draw();
}

Jetzt eine abstrakte Klasse mit dem Konstruktor erstellen Sie erzwingen möchten. Eigentlich, da es nun verfügbar ist, da die Zeit, die Sie Ihre ursprüngliche Frage schrieb, können wir ein wenig Phantasie bekommen hier und nutzen Generika in dieser Situation so, dass wir diese an andere Schnittstellen anpassen können, die die gleiche Funktionalität müssen möglicherweise aber unterschiedliche Konstruktor Anforderungen:

public abstract class MustInitialize<T>
{
    public MustInitialize(T parameters)
    {

    }
}

Jetzt müssen Sie eine neue Klasse erstellen, die sowohl von der IDrawable-Schnittstelle und der MustInitialize abstrakten Klasse erbt:

public class Drawable : MustInitialize<GraphicsDeviceManager>, IDrawable
{
    GraphicsDeviceManager _graphicsDeviceManager;

    public Drawable(GraphicsDeviceManager graphicsDeviceManager)
        : base (graphicsDeviceManager)
    {
        _graphicsDeviceManager = graphicsDeviceManager;
    }

    public void Update()
    {
        //use _graphicsDeviceManager here to do whatever
    }

    public void Draw()
    {
        //use _graphicsDeviceManager here to do whatever
    }
}

Dann nur eine Instanz von Drawable und Sie sind gut zu gehen:

IDrawable drawableService = new Drawable(myGraphicsDeviceManager);

Die kühle Sache ist, dass die neue Klasse Drawable wir noch gerade erstellt verhält sich wie das, was wir von einem IDrawable erwartet.

Wenn Sie mehr als einen Parameter an den MustInitialize Konstruktor übergeben müssen, können Sie eine Klasse erstellen, die Eigenschaften für alle Felder definiert Sie brauchen, um passieren.

Andere Tipps

Sie können nicht. Es ist gelegentlich ein Schmerz, aber man würde es nicht in der Lage sein zu nennen ohnehin normale Techniken.

In einer Blog-Post Ich habe vorgeschlagen, statische Schnittstellen denen nur verwendbar in generischer Typ Einschränkungen wäre -. aber könnte wirklich nützlich sein, IMO

Ein Punkt wäre es, wenn Sie könnte einen Konstruktor innerhalb einer Schnittstelle definieren, würden Sie Schwierigkeiten ableiten Klassen haben:

public class Foo : IParameterlessConstructor
{
    public Foo() // As per the interface
    {
    }
}

public class Bar : Foo
{
    // Yikes! We now don't have a parameterless constructor...
    public Bar(int x)
    {
    }
}

Ein sehr spät Beitrag ein weiteres Problem mit verknüpften Konstrukteuren zu demonstrieren. (Ich diese Frage entscheiden, weil es die klarste Artikulation des Problems hat). Angenommen, konnten wir haben:

interface IPerson
{
    IPerson(string name);
}

interface ICustomer
{
    ICustomer(DateTime registrationDate);
}

class Person : IPerson, ICustomer
{
    Person(string name) { }
    Person(DateTime registrationDate) { }
}

Dabei gilt vereinbarungsgemäß die Umsetzung des „Schnittstelle Konstruktor“ wird durch den Typ-Namen ersetzt.

Jetzt eine Instanz machen:

ICustomer a = new Person("Ernie");

Würden wir sagen, dass der Vertrag ICustomer befolgt wird?

Und was folgt aus:

interface ICustomer
{
    ICustomer(string address);
}

Sie können es nicht.

Schnittstellen Verträge definieren, die andere Objekte implementieren und haben daher keinen Zustand, der initialisiert werden muss.

Wenn Sie einig Zustand haben, das initialisiert werden muss, sollten Sie stattdessen mit einer abstrakten Basisklasse berücksichtigen.

Es ist nicht möglich, eine Schnittstelle zu schaffen, die Konstrukteurs definiert, aber es ist möglich, eine Schnittstelle zu definieren, die eine Art erzwingt einen paramerterless Konstruktor zu haben, obwohl wäre es eine sehr hässliche Syntax, die Generika verwendet ... ich bin eigentlich nicht so sicher, dass es wirklich ein gutes Codierungsmuster.

public interface IFoo<T> where T : new()
{
  void SomeMethod();
}

public class Foo : IFoo<Foo>
{
  // This will not compile
  public Foo(int x)
  {

  }

  #region ITest<Test> Members

  public void SomeMethod()
  {
    throw new NotImplementedException();
  }

  #endregion
}

Auf der anderen Seite, wenn Sie testen möchten, ob ein Typ mit einem paramerterless Konstruktor hat, können Sie tun, dass die Reflexion:

public static class TypeHelper
{
  public static bool HasParameterlessConstructor(Object o)
  {
    return HasParameterlessConstructor(o.GetType());
  }

  public static bool HasParameterlessConstructor(Type t)
  {
    // Usage: HasParameterlessConstructor(typeof(SomeType))
    return t.GetConstructor(new Type[0]) != null;
  }
}

Hope, das hilft.

Ich war auf der Suche auf diese Frage zurück, und ich dachte mir, vielleicht dieses Problem, das wir in die falsche Richtung aproaching. Schnittstellen ist vielleicht nicht der Weg zu gehen, wenn es sich um einen Konstruktor mit bestimmten Parametern definieren ... aber eine (abstrakte) Basisklasse ist.

Wenn Sie eine Basisklasse mit einem Konstruktor erstellen dort, die die Parameter akzeptiert Sie benötigen, jede Klasse, die derrives von ihm, sie versorgen muss.

public abstract class Foo
{
  protected Foo(SomeParameter x)
  {
    this.X = x;
  }

  public SomeParameter X { get; private set }
}

public class Bar : Foo // Bar inherits from Foo
{
  public Bar() 
    : base(new SomeParameter("etc...")) // Bar will need to supply the constructor param
  {
  }
}

Eine Möglichkeit, dieses Problem, das ich gefunden zu lösen, ist die Konstruktion in eine separate Fabrik trennen aus. Zum Beispiel habe ich eine abstrakte Klasse namens IQueueItem, und ich brauche einen Weg, um dieses Ziel zu und von einem anderen Objekt (CloudQueueMessage) zu übersetzen. Also auf der Schnittstelle IQueueItem ich habe -

public interface IQueueItem
{
    CloudQueueMessage ToMessage();
}

Nun, ich brauche auch eine Möglichkeit für meine aktuellen Warteschlangen-Klasse einen CloudQueueMessage zurück zu einem IQueueItem zu übersetzen - also die Notwendigkeit einer statischen Konstruktion wie IQueueItem objMessage = ItemType.FromMessage. Stattdessen definiert ich eine andere Schnittstelle IQueueFactory -

public interface IQueueItemFactory<T> where T : IQueueItem
{
    T FromMessage(CloudQueueMessage objMessage);
}

Jetzt kann ich endlich meine generische Queue-Klasse ohne den neuen () Constraint schreiben, die in meinem Fall das Hauptproblem war.

public class AzureQueue<T> where T : IQueueItem
{
    private IQueueItemFactory<T> _objFactory;
    public AzureQueue(IQueueItemFactory<T> objItemFactory)
    {
        _objFactory = objItemFactory;
    }


    public T GetNextItem(TimeSpan tsLease)
    {
        CloudQueueMessage objQueueMessage = _objQueue.GetMessage(tsLease);
        T objItem = _objFactory.FromMessage(objQueueMessage);
        return objItem;
    }
}

Jetzt kann ich eine Instanz erstellen, die die Kriterien für mich erfüllt

 AzureQueue<Job> objJobQueue = new JobQueue(new JobItemFactory())

hoffentlich hilft dies jemand anderen aus, einen Tag, offensichtlich eine Menge internen Code entfernt, um zu versuchen, das Problem zu zeigen und Lösung

Der allgemeine Fabrik Ansatz scheint immer noch ideal. Sie würden wissen, dass die Fabrik einen Parameter benötigt, und es wäre einfach so passieren, dass diese Parameter entlang an den Konstruktor des Objekts übergeben werden instanziiert wird.

Beachten Sie, ist dies nur Pseudo-Code überprüft Syntax, eine Laufzeit Vorbehalt kann ich hier fehlt:

public interface IDrawableFactory
{
    TDrawable GetDrawingObject<TDrawable>(GraphicsDeviceManager graphicsDeviceManager) 
              where TDrawable: class, IDrawable, new();
}

public class DrawableFactory : IDrawableFactory
{
    public TDrawable GetDrawingObject<TDrawable>(GraphicsDeviceManager graphicsDeviceManager) 
                     where TDrawable : class, IDrawable, new()
    {
        return (TDrawable) Activator
                .CreateInstance(typeof(TDrawable), 
                                graphicsDeviceManager);
    }

}

public class Draw : IDrawable
{
 //stub
}

public class Update : IDrawable {
    private readonly GraphicsDeviceManager _graphicsDeviceManager;

    public Update() { throw new NotImplementedException(); }

    public Update(GraphicsDeviceManager graphicsDeviceManager)
    {
        _graphicsDeviceManager = graphicsDeviceManager;
    }
}

public interface IDrawable
{
    //stub
}
public class GraphicsDeviceManager
{
    //stub
}

Ein Beispiel für eine mögliche Nutzung:

    public void DoSomething()
    {
        var myUpdateObject = GetDrawingObject<Update>(new GraphicsDeviceManager());
        var myDrawObject = GetDrawingObject<Draw>(null);
    }

Zugegeben, würden Sie wollen nur die Instanzen über das Werk schaffen zu gewährleisten haben Sie immer ein entsprechend initialisiert Objekt. Vielleicht mit Rahmen ein Dependency Injection wie Autofac Sinn machen würde; Update () kann mit der "fragen", um den IoC-Container für ein neues GraphicsDeviceManager Objekt.

Eine Möglichkeit, dieses Problem zu lösen, ist zu Leverage-Generika und die neuen () Einschränkung.

Stattdessen Konstruktor als Methode / Funktion auszudrücken, können Sie es als eine Fabrik Klasse / Schnittstelle zum Ausdruck bringen können. Wenn Sie die neue () generische Einschränkung bei jeder Aufruf-Website angeben, die ein Objekt der Klasse erstellen muss, werden Sie in der Lage sein Konstruktorargumente entsprechend zu übergeben.

Für Ihr IDrawable Beispiel:

public interface IDrawable
{
    void Update();
    void Draw();
}

public interface IDrawableConstructor<T> where T : IDrawable
{
    T Construct(GraphicsDeviceManager manager);
}


public class Triangle : IDrawable
{
    public GraphicsDeviceManager Manager { get; set; }
    public void Draw() { ... }
    public void Update() { ... }
    public Triangle(GraphicsDeviceManager manager)
    {
        Manager = manager;
    }
}


public TriangleConstructor : IDrawableConstructor<Triangle>
{
    public Triangle Construct(GraphicsDeviceManager manager)
    {
        return new Triangle(manager);
    } 
}

Nun, wenn Sie es verwenden:

public void SomeMethod<TBuilder>(GraphicsDeviceManager manager)
  where TBuilder: IDrawableConstructor<Triangle>, new()
{
    // If we need to create a triangle
    Triangle triangle = new TBuilder().Construct(manager);

    // Do whatever with triangle
}

Sie können sogar alle Erstellungsmethoden in einer einzigen Klasse mit expliziter Interface-Implementierung konzentrieren:

public DrawableConstructor : IDrawableConstructor<Triangle>,
                             IDrawableConstructor<Square>,
                             IDrawableConstructor<Circle>
{
    Triangle IDrawableConstructor<Triangle>.Construct(GraphicsDeviceManager manager)
    {
        return new Triangle(manager);
    } 

    Square IDrawableConstructor<Square>.Construct(GraphicsDeviceManager manager)
    {
        return new Square(manager);
    } 

    Circle IDrawableConstructor<Circle>.Construct(GraphicsDeviceManager manager)
    {
        return new Circle(manager);
    } 
}

Um es zu verwenden:

public void SomeMethod<TBuilder, TShape>(GraphicsDeviceManager manager)
  where TBuilder: IDrawableConstructor<TShape>, new()
{
    // If we need to create an arbitrary shape
    TShape shape = new TBuilder().Construct(manager);

    // Do whatever with the shape
}

Eine andere Möglichkeit ist durch Lambda-Ausdrücke wie initializers verwenden. An einem gewissen Punkt früh in der Aufrufhierarchie, werden Sie wissen, welche Objekte Sie instanziiert werden müssen (das heißt, wenn Sie erstellen oder einen Verweis auf Ihre GraphicsDeviceManager Objekt bekommen). Sobald Sie es haben, den Lambda-Pass

() => new Triangle(manager) 

In den nachfolgenden Methoden, so dass sie wissen, wie ein Dreieck zu erstellen, die von da an. Wenn Sie nicht alle möglichen Methoden bestimmen können, die Sie benötigen, können Sie immer ein Wörterbuch von Typen erstellen, die IDrawable mit Reflexion implementieren und den Lambda-Ausdruck registrieren oben in einem Wörterbuch gezeigt, dass Sie entweder speichern in einem gemeinsamen Standort oder passieren entlang zu weitere Funktion aufruft.

Sie können dies tun mit Generika Trick, aber es ist immer noch anfällig für was Jon Skeet schrieb:

public interface IHasDefaultConstructor<T> where T : IHasDefaultConstructor<T>, new()
{
}

Klasse, die diese Schnittstelle implementiert, muss parameterlosen Konstruktor haben:

public class A : IHasDefaultConstructor<A> //Notice A as generic parameter
{
    public A(int a) { } //compile time error
}

Der Zweck einer Schnittstelle ist es, eine bestimmte Objektsignatur zu erzwingen. Es sollte ausdrücklich nicht darum kümmern, wie ein Objekt intern funktioniert. Daher ist wirklich ein Konstruktor in einer Schnittstelle nicht Sinn aus konzeptioneller Sicht machen.

Es gibt einige Alternativen aber:

  • Erstellen Sie eine abstrakte Klasse, die als eine minimale Standardimplementierung wirkt. Diese Klasse sollte die Konstrukteure haben Sie Klassen erwarten Umsetzung müssen.

  • Wenn Sie nicht das Übermaß dagegen, verwenden Sie die Muster und Abstrakte eine Methode in der Factory-Klasse-Schnittstelle deklariert werden, die die erforderlichen haben Unterschriften.

  • Führen Sie den GraphicsDeviceManager als Parameter an den Update und Draw Methoden.

  • Verwenden Sie einen Kompositorische Objektorientierte Programmierung Rahmen den GraphicsDeviceManager in den Teil des Objekts zu übergeben, die es erfordert. Dies ist eine ziemlich experimentelle Lösung meiner Meinung nach.

Die Situation, die Sie beschreiben, ist nicht einfach, in der Regel zu behandeln. Ein ähnlicher Fall würden Unternehmen in einem Business-Anwendung, die Zugriff auf die Datenbank erforderlich ist.

Sie dies nicht tun.

Der Konstruktor ist ein Teil der Klasse, die eine Schnittstelle implementieren kann. Die Schnittstelle ist nur ein Vertrag von Methoden muss die Klasse implementieren.

Es wäre sehr nützlich sein, wenn es möglich wäre, in Schnittstellen zu definieren Konstrukteure.

Da eine Schnittstelle ist ein Vertrag, der in der angegebenen Weise verwendet werden muß. Der folgende Ansatz könnte eine brauchbare Alternative für einige Szenarien sein:

public interface IFoo {

    /// <summary>
    /// Initialize foo.
    /// </summary>
    /// <remarks>
    /// Classes that implement this interface must invoke this method from
    /// each of their constructors.
    /// </remarks>
    /// <exception cref="InvalidOperationException">
    /// Thrown when instance has already been initialized.
    /// </exception>
    void Initialize(int a);

}

public class ConcreteFoo : IFoo {

    private bool _init = false;

    public int b;

    // Obviously in this case a default value could be used for the
    // constructor argument; using overloads for purpose of example

    public ConcreteFoo() {
        Initialize(42);
    }

    public ConcreteFoo(int a) {
        Initialize(a);
    }

    public void Initialize(int a) {
        if (_init)
            throw new InvalidOperationException();
        _init = true;

        b = a;
    }

}

Eine Möglichkeit, eine Art Konstruktor zu zwingen, ist nur Getters in Schnittstelle zu erklären, die dann, dass die implementierende Klasse bedeuten könnte, muss eine Methode haben, idealerweise einen Konstruktor, den eingestellten Wert (privately) für ihn zu haben.

Während Sie keinen Konstruktor Signatur in einer Schnittstelle definieren können, ich fühle es wert ist zu erwähnen, dass dies ein Punkt sein kann, eine abstrakte Klasse zu betrachten. Abstrakte Klassen können nicht implementiert (Auszug) Methodensignaturen in der gleichen Weise wie eine Schnittstelle definieren, sondern auch umgesetzt (Beton) Methoden und Konstruktoren.

Der Nachteil ist, dass, weil es sich um eine Art von Klasse ist, kann sie nicht für jede der Mehrfachvererbung Typ-Szenarien verwendet werden, die eine Schnittstelle kann.

Ich benutze das folgende Muster es beschuss zu machen.

  • Ein Entwickler, der seine Klasse von der Basis ergibt sich versehentlich nicht öffentlich zugänglich Konstruktor
  • Die letzte Klasse Entwickler sind gezwungen, durch die gemeinsame create-Methode gehen
  • Alles ist typsicher sind keine Gußteile erforderlich
  • Es ist 100% flexibel und kann überall wiederverwendet werden, in dem Sie Ihre eigene Basis definieren Klasse.
  • Ausprobieren Sie es Änderungen an den Basisklassen, ohne dass nicht brechen kann (ausgenommen wenn Sie eine veraltete Flagge ohne Fehler-Flag auf true gesetzt definieren, aber auch dann am Ende mit einer Warnung nach oben)

        public abstract class Base<TSelf, TParameter>
        where TSelf : Base<TSelf, TParameter>, new()
    {
        protected const string FactoryMessage = "Use YourClass.Create(...) instead";
        public static TSelf Create(TParameter parameter)
        {
            var me = new TSelf();
            me.Initialize(parameter);
    
            return me;
        }
    
        [Obsolete(FactoryMessage, true)]
        protected Base()
        {
        }
    
    
    
        protected virtual void Initialize(TParameter parameter)
        {
    
        }
    }
    
    public abstract class BaseWithConfig<TSelf, TConfig>: Base<TSelf, TConfig>
        where TSelf : BaseWithConfig<TSelf, TConfig>, new()
    {
        public TConfig Config { get; private set; }
    
        [Obsolete(FactoryMessage, true)]
        protected BaseWithConfig()
        {
        }
        protected override void Initialize(TConfig parameter)
        {
            this.Config = parameter;
        }
    }
    
    public class MyService : BaseWithConfig<MyService, (string UserName, string Password)>
    {
        [Obsolete(FactoryMessage, true)]
        public MyService()
        {
        }
    }
    
    public class Person : Base<Person, (string FirstName, string LastName)>
    {
        [Obsolete(FactoryMessage,true)]
        public Person()
        {
        }
    
        protected override void Initialize((string FirstName, string LastName) parameter)
        {
            this.FirstName = parameter.FirstName;
            this.LastName = parameter.LastName;
        }
    
        public string LastName { get; private set; }
    
        public string FirstName { get; private set; }
    }
    
    
    
    [Test]
    public void FactoryTest()
    {
        var notInitilaizedPerson = new Person(); // doesn't compile because of the obsolete attribute.
        Person max = Person.Create(("Max", "Mustermann"));
        Assert.AreEqual("Max",max.FirstName);
    
        var service = MyService.Create(("MyUser", "MyPassword"));
        Assert.AreEqual("MyUser", service.Config.UserName);
    }
    

EDIT: Und hier ist ein Beispiel auf der Zeichnung Beispiel aus, dass sogar Schnittstelle Abstraktion

erzwingt
        public abstract class BaseWithAbstraction<TSelf, TInterface, TParameter>
        where TSelf : BaseWithAbstraction<TSelf, TInterface, TParameter>, TInterface, new()
    {
        [Obsolete(FactoryMessage, true)]
        protected BaseWithAbstraction()
        {
        }

        protected const string FactoryMessage = "Use YourClass.Create(...) instead";
        public static TInterface Create(TParameter parameter)
        {
            var me = new TSelf();
            me.Initialize(parameter);

            return me;
        }

        protected virtual void Initialize(TParameter parameter)
        {

        }
    }



    public abstract class BaseWithParameter<TSelf, TInterface, TParameter> : BaseWithAbstraction<TSelf, TInterface, TParameter>
        where TSelf : BaseWithParameter<TSelf, TInterface, TParameter>, TInterface, new()
    {
        protected TParameter Parameter { get; private set; }

        [Obsolete(FactoryMessage, true)]
        protected BaseWithParameter()
        {
        }
        protected sealed override void Initialize(TParameter parameter)
        {
            this.Parameter = parameter;
            this.OnAfterInitialize(parameter);
        }

        protected virtual void OnAfterInitialize(TParameter parameter)
        {
        }
    }


    public class GraphicsDeviceManager
    {

    }
    public interface IDrawable
    {
        void Update();
        void Draw();
    }

    internal abstract class Drawable<TSelf> : BaseWithParameter<TSelf, IDrawable, GraphicsDeviceManager>, IDrawable 
        where TSelf : Drawable<TSelf>, IDrawable, new()
    {
        [Obsolete(FactoryMessage, true)]
        protected Drawable()
        {
        }

        public abstract void Update();
        public abstract void Draw();
    }

    internal class Rectangle : Drawable<Rectangle>
    {
        [Obsolete(FactoryMessage, true)]
        public Rectangle()
        {
        }

        public override void Update()
        {
            GraphicsDeviceManager manager = this.Parameter;
            // TODo  manager
        }

        public override void Draw()
        {
            GraphicsDeviceManager manager = this.Parameter;
            // TODo  manager
        }
    }
    internal class Circle : Drawable<Circle>
    {
        [Obsolete(FactoryMessage, true)]
        public Circle()
        {
        }

        public override void Update()
        {
            GraphicsDeviceManager manager = this.Parameter;
            // TODo  manager
        }

        public override void Draw()
        {
            GraphicsDeviceManager manager = this.Parameter;
            // TODo  manager
        }
    }


    [Test]
    public void FactoryTest()
    {
        // doesn't compile because interface abstraction is enforced.
        Rectangle rectangle = Rectangle.Create(new GraphicsDeviceManager());

        // you get only the IDrawable returned.
        IDrawable service = Circle.Create(new GraphicsDeviceManager());
    }

Wenn ich verstand OP richtig, wir wollen einen Vertrag erzwingen, wo GraphicsDeviceManager immer durch die Implementierung von Klassen initialisiert wird. Ich hatte ein ähnliches Problem, und ich wurde nach einer besseren Lösung suchen, aber das ist das Beste, was ich mich vorstellen kann:

Fügen Sie einen SetGraphicsDeviceManager (GraphicsDeviceManager GDO) an die Schnittstelle, und auf diese Weise die Umsetzung der Klassen gezwungen werden, eine Logik zu schreiben, die einen Anruf von Konstruktor erforderlich sein wird.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top