我想使用 .NET Standard 2.0 库项目在 .NET Framework 4.7.2 WinForms 和 .NET 6.0 Blazor 应用程序之间共享代码。我应该使用依赖注入来实现依赖于目标应用程序的库中的方法吗?例如。在使用 WinForms 或 Blazor 显示用户消息时?
如果依赖注入是要走的路,你能提供一个关于如何实现上面例子的大纲吗?没有依赖注入容器能做到吗?
我经常用我的应用程序做这种事情,这些应用程序在 WinForms 和 Xamarin 之类的东西之间是跨平台的。我发现执行此操作的一种更简单的方法是制作可移植库类
abstract
,强制客户端继承提供平台相关代码的类。让您的客户使用 RuntimePlatform
枚举来标识自己也很方便。或者,virtual
方法会起作用,但会产生“无声失败”,除非它们抛出 NotImplementedException
在这一点上为什么不 abstract
它。
using System.Diagnostics;
using System.Threading.Tasks;
namespace net6_portable_library
{
public enum RuntimePlatform
{
WinOS,
Android,
iOS,
Web,
MAUI,
}
public abstract class BusinessLogic
{
public BusinessLogic(RuntimePlatform platform) => RuntimePlatform = platform;
protected abstract Task<bool> DisplayAlert(string title, string message, string accept, string cancel);
public async Task<bool> TestPopup()
{
bool result = await DisplayAlert(
title: "Demo",
message: $"Is {RuntimePlatform} popup visible?", accept: "Yes", cancel: "No");
Debug.WriteLine($"Dialog returned {result}");
return result;
}
public RuntimePlatform RuntimePlatform { get; }
}
}
我成功的另一个选择是在特定于平台的客户端可以填充的 PCL 库中拥有
interface
或 delegate
成员。
WinForms 客户端
using System;
using System.Threading.Tasks;
using System.Windows.Forms;
using net6_portable_library;
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
buttonTestLibrary.Click += onClickTestLibrary;
}
private void onClickTestLibrary(object sender, EventArgs e)
{
_ = _lib.TestPopup();
}
// Consume library
BusinessLogic _lib = new PlatformBusinessLogic(RuntimePlatform.WinOS);
}
class PlatformBusinessLogic : BusinessLogic
{
public PlatformBusinessLogic(RuntimePlatform platform) : base(platform) { }
protected override async Task<bool> DisplayAlert(string title, string message, string accept, string cancel)
{
var buttons = $"{accept}.{cancel}".ToUpper();
switch (buttons)
{
case "YES.NO":
bool result = false;
await Task.Run(() =>
{
result = DialogResult.Yes.Equals
(
MessageBox.Show(text: message, caption: title, MessageBoxButtons.YesNo)
);
});
return result;
default:
throw new NotImplementedException($"TODO: Handler for {buttons}.");
}
}
}
安卓客户端
namespace maui_client_of_portable_library
{
public partial class MainPage : ContentPage
{
int count = 0;
public MainPage()
{
InitializeComponent();
}
// Consume library
BusinessLogic _lib = new PlatformBusinessLogic(RuntimePlatform.MAUI);
private void onClickTestLibrary(object sender, EventArgs e)
{
_ = _lib.TestPopup();
}
}
class PlatformBusinessLogic : BusinessLogic
{
public PlatformBusinessLogic(RuntimePlatform platform) : base(platform) { }
protected override async Task<bool> DisplayAlert(string title, string message, string accept, string cancel)
{
return await Shell.Current.CurrentPage.DisplayAlert(title, message, accept, cancel);
}
}
}