创建新式 WPF 应用程序涉及混合可靠的体系结构模式和框架,以确保可维护性、可伸缩性和灵活性。本文讨论如何使用 MVVM(Model-View-ViewModel)模式、用于数据库集成的 EF Core、插件体系结构和用于依赖项注入的 Autofac 来开发 WPF 应用程序。一个关键的重点是实施一个强大的用户管理系统,包括身份验证、授权和角色管理。此外,我们还将探索使用事件聚合器和共享服务提供商的插件之间的通信,并在主窗口中演示插件版本控制和加载。
我们应用程序的主要组件包括:
Autofac使我们能够以灵活且可扩展的方式管理依赖项。下面是 DI 容器的示例配置:
public class Bootstrapper
{
public IContainer Bootstrap()
{
var builder = new ContainerBuilder();
// Register MVVM components
builder.RegisterType<MainViewModel>().AsSelf();
builder.RegisterType<MainWindow>().AsSelf();
// Register EF Core DbContext
builder.RegisterType<AppDbContext>().AsSelf().InstancePerLifetimeScope();
// Register Plugin Loader
builder.RegisterType<PluginLoader>().As<IPluginLoader>();
// Register Event Aggregator
builder.RegisterType<EventAggregator>().As<IEventAggregator>().SingleInstance();
// Register AuthService
builder.RegisterType<AuthService>().As<IAuthService>().InstancePerLifetimeScope();
return builder.Build();
}
}
该应用程序在启动期间加载插件并显示一个简单的登录页面。插件的加载方式如下:
public interface IPlugin
{
void Initialize(IContainer container);
}
public class PluginLoader : IPluginLoader
{
private readonly IContainer _container;
public PluginLoader(IContainer container)
{
_container = container;
}
public void LoadPlugins(string path)
{
var pluginAssemblies = Directory.GetFiles(path, "*.dll")
.Select(Assembly.LoadFrom);
foreach (var assembly in pluginAssemblies)
{
var pluginTypes = assembly.GetTypes().Where(t => typeof(IPlugin).IsAssignableFrom(t) && !t.IsAbstract);
foreach (var pluginType in pluginTypes)
{
var plugin = (IPlugin)Activator.CreateInstance(pluginType);
plugin.Initialize(_container);
}
}
}
}
为了显示登陆页面,我们确保 MainWindow 设置正确:
public partial class MainWindow : Window
{
private readonly IPluginLoader _pluginLoader;
public MainWindow(IPluginLoader pluginLoader)
{
InitializeComponent();
_pluginLoader = pluginLoader;
Loaded += OnLoaded;
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
_pluginLoader.LoadPlugins("Plugins");
// Display landing page content
DataContext = new MainViewModel();
}
}
我们首先定义用户、角色及其关系的数据模型:
public class User
{
public int Id { get; set; }
public string Username { get; set; }
public string PasswordHash { get; set; }
public ICollection<UserRole> UserRoles { get; set; }
}
public class Role
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<UserRole> UserRoles { get; set; }
}
public class UserRole
{
public int UserId { get; set; }
public User User { get; set; }
public int RoleId { get; set; }
public Role Role { get; set; }
}
AuthService 处理身份验证和授权:
public interface IAuthService
{
User Authenticate(string username, string password);
bool Authorize(User user, string role);
}
public class AuthService : IAuthService
{
private readonly AppDbContext _context;
public AuthService(AppDbContext context)
{
_context = context;
}
public User Authenticate(string username, string password)
{
var user = _context.Users.Include(u => u.UserRoles).ThenInclude(ur => ur.Role)
.FirstOrDefault(u => u.Username == username);
if (user == null || !VerifyPassword(user.PasswordHash, password))
{
return null;
}
return user;
}
public bool Authorize(User user, string role)
{
return user.UserRoles.Any(ur => ur.Role.Name == role);
}
private bool VerifyPassword(string hashedPassword, string password)
{
// Implement password verification logic here
return true;
}
}
事件聚合器有助于插件之间的解耦通信:
public interface IEventAggregator
{
void Publish<TEvent>(TEvent eventToPublish);
void Subscribe<TEvent>(Action<TEvent> eventHandler);
}
public class EventAggregator : IEventAggregator
{
private readonly ConcurrentDictionary<Type, List<object>> _subscribers = new();
public void Publish<TEvent>(TEvent eventToPublish)
{
if (_subscribers.TryGetValue(typeof(TEvent), out var handlers))
{
foreach (var handler in handlers.OfType<Action<TEvent>>())
{
handler(eventToPublish);
}
}
}
public void Subscribe<TEvent>(Action<TEvent> eventHandler)
{
_subscribers.AddOrUpdate(
typeof(TEvent),
_ => new List<object> { eventHandler },
(_, handlers) => { handlers.Add(eventHandler); return handlers; }
);
}
}
为了确保插件兼容,我们实施了版本检查:
public interface IPluginMetadata
{
string Name { get; }
Version Version { get; }
}
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class PluginAttribute : Attribute, IPluginMetadata
{
public string Name { get; }
public Version Version { get; }
public PluginAttribute(string name, string version)
{
Name = name;
Version = Version.Parse(version);
}
}
public class PluginLoader : IPluginLoader
{
private readonly IContainer _container;
public PluginLoader(IContainer container)
{
_container = container;
}
public void LoadPlugins(string path)
{
var pluginAssemblies = Directory.GetFiles(path, "*.dll")
.Select(Assembly.LoadFrom);
foreach (var assembly in pluginAssemblies)
{
var pluginTypes = assembly.GetTypes()
.Where(t => typeof(IPlugin).IsAssignableFrom(t) &&
t.GetCustomAttribute<PluginAttribute>() != null);
foreach (var pluginType in pluginTypes)
{
var metadata = pluginType.GetCustomAttribute<PluginAttribute>();
if (IsCompatible(metadata))
{
var plugin = (IPlugin)Activator.CreateInstance(pluginType);
plugin.Initialize(_container);
}
}
}
}
private bool IsCompatible(IPluginMetadata metadata)
{
// Implement compatibility check logic here
return true;
}
}
上述体系结构为开发模块化和可扩展的 WPF 应用程序奠定了坚实的基础。通过集成 MVVM 模式、EF Core、插件架构和 Autofac,应用程序变得高度可维护且面向未来。实施全面的用户管理系统,以及线程安全的插件通信,确保了可用性和可靠性。精心规划的插件版本控制策略可保持应用程序的兼容性和可扩展性。