.NET Framework
Zarządzane ramy rozszerzalności
Szukaj…
Uwagi
Jedną z wielkich zalet MEF w porównaniu z innymi technologiami obsługującymi wzorzec inwersji kontroli jest to, że obsługuje rozwiązywanie zależności, które nie są znane w czasie projektowania, bez potrzeby dużej (jeśli w ogóle) konfiguracji.
Wszystkie przykłady wymagają odwołania do zestawu System.ComponentModel.Composition.
Ponadto wszystkie (podstawowe) przykłady wykorzystują je jako przykładowe obiekty biznesowe:
using System.Collections.ObjectModel;
namespace Demo
{
public sealed class User
{
public User(int id, string name)
{
this.Id = id;
this.Name = name;
}
public int Id { get; }
public string Name { get; }
public override string ToString() => $"User[Id: {this.Id}, Name={this.Name}]";
}
public interface IUserProvider
{
ReadOnlyCollection<User> GetAllUsers();
}
}
Eksportowanie typu (podstawowe)
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel.Composition;
namespace Demo
{
[Export(typeof(IUserProvider))]
public sealed class UserProvider : IUserProvider
{
public ReadOnlyCollection<User> GetAllUsers()
{
return new List<User>
{
new User(0, "admin"),
new User(1, "Dennis"),
new User(2, "Samantha"),
}.AsReadOnly();
}
}
}
Można to zdefiniować praktycznie wszędzie; liczy się tylko to, że aplikacja wie, gdzie jej szukać (za pośrednictwem tworzonych przez siebie ComposablePartCatalogs).
Importowanie (podstawowe)
using System;
using System.ComponentModel.Composition;
namespace Demo
{
public sealed class UserWriter
{
[Import(typeof(IUserProvider))]
private IUserProvider userProvider;
public void PrintAllUsers()
{
foreach (User user in this.userProvider.GetAllUsers())
{
Console.WriteLine(user);
}
}
}
}
Jest to typ zależny od IUserProvider
, który można zdefiniować w dowolnym miejscu. Podobnie jak w poprzednim przykładzie, wszystko, co się liczy, to to, że aplikacja wie, gdzie szukać pasującego eksportu (za pośrednictwem tworzonych przez siebie ComposablePartCatalogs).
Łączenie (podstawowe)
Zobacz inne (podstawowe) przykłady powyżej.
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
namespace Demo
{
public static class Program
{
public static void Main()
{
using (var catalog = new ApplicationCatalog())
using (var exportProvider = new CatalogExportProvider(catalog))
using (var container = new CompositionContainer(exportProvider))
{
exportProvider.SourceProvider = container;
UserWriter writer = new UserWriter();
// at this point, writer's userProvider field is null
container.ComposeParts(writer);
// now, it should be non-null (or an exception will be thrown).
writer.PrintAllUsers();
}
}
}
}
Tak długo, jak coś w ścieżce wyszukiwania zestawu aplikacji ma [Export(typeof(IUserProvider))]
, odpowiedni import UserWriter
będzie zadowolony i użytkownicy zostaną wydrukowani.
Można używać innych typów katalogów (np. DirectoryCatalog
) zamiast (lub oprócz) ApplicationCatalog
, aby szukać w innych miejscach eksportu, które spełniają wymagania importu.