Andere haben bereits gute Antworten zum Generieren von Code zur Laufzeit gegeben, daher dachte ich, ich würde Ihren zweiten Absatz ansprechen. Ich habe einige Erfahrungen damit und möchte nur eine Lektion teilen, die ich aus diesen Erfahrungen gelernt habe.
Zumindest könnte ich eine Schnittstelle definieren, die implementiert werden müsste, und dann einen Code-Abschnitt bereitstellen, der diese Schnittstelle implementiert.
Möglicherweise liegt ein Problem vor, wenn Sie einen interfaceals Basistyp verwenden. Wenn Sie interfacein Zukunft alle vorhandenen vom Client bereitgestellten Klassen, die das interfaceJetzt implementieren, um eine einzige neue Methode erweitern, werden sie abstrakt. Dies bedeutet, dass Sie die vom Client bereitgestellte Klasse zur Laufzeit nicht kompilieren oder instanziieren können.
Ich hatte dieses Problem, als es an der Zeit war, nach etwa einem Jahr Versand der alten Schnittstelle und nach der Verteilung einer großen Menge von "Legacy" -Daten, die unterstützt werden mussten, eine neue Methode hinzuzufügen. Am Ende habe ich eine neue Schnittstelle erstellt, die von der alten geerbt wurde, aber dieser Ansatz machte es schwieriger, die vom Client bereitgestellten Klassen zu laden und zu instanziieren, da ich überprüfen musste, welche Schnittstelle verfügbar war.
Eine Lösung, an die ich damals dachte, bestand darin, stattdessen eine tatsächliche Klasse als Basistyp wie den folgenden zu verwenden. Die Klasse selbst kann als abstrakt markiert werden, aber alle Methoden sollten leere virtuelle Methoden sein (keine abstrakten Methoden). Clients können dann die gewünschten Methoden überschreiben, und ich kann der Basisklasse neue Methoden hinzufügen, ohne den vom Client bereitgestellten Code ungültig zu machen.
public abstract class BaseClass
{
public virtual void Foo1() { }
public virtual bool Foo2() { return false; }
...
}
Unabhängig davon, ob dieses Problem auftritt, sollten Sie überlegen, wie Sie die Schnittstelle zwischen Ihrer Codebasis und dem vom Client bereitgestellten Code versionieren.