Questa risposta sarà specifica per il mio contenitore.
La nostra applicazione attuale deve iniziare a supportare il caricamento dinamico e il "collegamento" di diversi "plug-in"/"estensioni" che sono sconosciuti all'applicazione in fase di compilazione.
Per poterlo fare è necessario definire alcune interfacce di estensione che si inseriscono in una libreria di classi che verrà condivisa tra l'applicazione e tutti i plug-in.
Per esempio, se vuoi le applicazioni per essere in grado di aggiungere cose al menu delle applicazioni è possibile creare la seguente interfaccia:
class ApplicationMenu
{
// The "File" menu
IMenuItem File { get; }
}
interface IMenuRegistrar
{
void Register(ApplicationMenu menu);
}
Il che significa che il vostro plugin può creare la seguente classe:
[Component]
public class CoolPluginMenuRegistrar : IMenuRegistrar
{
public void Register(ApplicationMenu menu)
{
menu.File.Add("mnuMyPluginMenuName", "Load jokes");
}
}
L'attributo [Component]
è utilizzato dal mio contenitore in modo che possa rilevare e registrare automaticamente le classi per voi.
Tutto quello che devi fare per registrare tutti i punti di estensione, come quello di cui sopra è questo:
public class Program
{
public static void Main(string[] args)
{
var registrar = new ContainerRegistrar();
registrar.RegisterComponents(Lifetime.Transient, Environment.CurrentDirectory, "MyApp.Plugin.*.dll");
var container = registrar.Build();
// all extension points have been loaded. To load all menu extensions simply do something like:
var menu = GetMainMenu();
foreach (var registrar in container.ResolveAll<IMenuRegistrar>())
{
registrar.Register(menu);
}
}
}
Queste estensioni sarebbero "agganciato" in diverse aree di applicazione, come ad esempio ADED come gestori di eventi di alcune classi. Da quanto ne so, i contenitori IoC consentono di scoprire dinamicamente oggetti in fase di runtime e di registrarli in un contenitore.
Sì. Ottieni tutto questo.
È un contenitore IoC in grado di eseguire questo aggancio anche in vari eventi? O questo compito è più facile da fare senza un simile quadro?
Sì. Ho un meccanismo per eventi incorporato. Inserire le classi di eventi (classi .NET regolari in librerie di classi condivise). Il Basta iscriversi su di loro mediante l'attuazione di un'interfaccia:
[Component]
public class ReplyEmailNotification : ISubscriberOf<ReplyPosted>
{
ISmtpClient _client;
IUserQueries _userQueries;
public ReplyEmailNotification(ISmtpClient client, IUserQueries userQueries)
{
_client = client;
_userQueries = userQueries;
}
public void Invoke(ReplyPosted e)
{
var user = _userQueries.Get(e.PosterId);
_client.Send(new MailMessage(user.Email, "bla bla"));
}
}
e pubblicare eventi:
DomainEvent.Publish(new ReplyPosted(user.Id, "This is a subject"));
Gli eventi possono essere gestiti da alcun plugin, purché:
- Impossibile accedere la classe evento
- Sono stati registrati nel contenitore (
[Component]
o registrazione manuale)
- Implementa
ISubscriberOf<T>
E 'comune che il plugin stesso offrono un metodo Registrati per fare la registrazione?
Sì. Attraverso diverse interfacce che sono definite come punti di estensione in un assembly condiviso.
Se l'IoC esegue la registrazione? (come si fa di solito?)
Sì. Se il contenitore lo fornisce.
In che modo è possibile definire facilmente i punti di estensione quando si utilizza un contenitore IoC?
È possibile leggere su di esso in modo più dettagliato qui: http://www.codeproject.com/Articles/440665/Having-fun-with-Griffin-Container
Con MEF, ogni "parte" è un'implementazione di qualche interfaccia. Ciò significa che per ogni punto di estensibilità dovrebbe essere creata una nuova interfaccia? Ad esempio, ho 3 eventi: OnA, OnB, OnC. Come faccio ad abilitare i plug-in a questi eventi con MEF? (senza definire 3 diverse interfacce). –
Non capisco davvero la domanda: se OnA, OnB e OnC sono associati logicamente in modo tale da poter essere sensibilmente parte di una singola interfaccia, renderli un'unica interfaccia. Se non sono associati, rendili parte di interfacce separate. O ho frainteso la tua domanda? –
Voglio dire, se ho molti eventi diversi su cui voglio registrarmi dinamicamente, ognuno di essi deve definire esplicitamente di importare una determinata interfaccia. Ciò significa che devo definire 3 diverse interfacce (una per ogni tipo di evento). Diciamo che ho 1 interfaccia e 3 eventi importano questa implementazione dell'interfaccia. Tutti e 3 gli eventi importeranno tutte le implementazioni, che non è quello che sto cercando. –