问题描述
从我的 .NETStandard 2.1 库中,我无权访问 MediaPlayer 类。 当事件发生在其方法之一中时,来自同一个库的服务应该播放 mp3 文件
我的主要项目是一个 .NET5 WPF,这个小代码在单独测试时效果很好:
private void PlayAlert()
{
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.Open(new Uri("alert.mp3",UriKind.Relative));
mediaPlayer.Play();
}
您如何将我的库与仅在此处有效的私有方法干净利落地连接起来?
谢谢!
解决方法
您可以在您的类库中创建一个 ISoundPlayer
接口,并且在您需要的任何地方,将其作为依赖项传递给类的构造函数。
然后在您的 Wpf 应用程序中,在 MySoundPlayer 类中实现该接口,并且每当您想要实例化依赖于 ISoundPlayer 的类库的这些类之一时,请将 MySoundPlayer 传递给它们。
还有一些其他可能的解决方案,如果您有兴趣了解它们,请阅读有关控制反转的答案底部的注释。
示例
以下示例未使用任何 DI 框架,而是创建了一个类库,该类库具有一个 MyClass,该类库依赖于名为 ISoundPlayer 的接口。然后在另一个项目中,一个 Wpf 应用程序,实现 ISoundPlayer,实例化 MyClass 并将 ISoundPlayer 的实现传递给它。您可以使用 DI 库(这超出本 q/a 的范围)来使用它。
请按照以下步骤操作:
-
创建 WPF 应用程序 MyWpfApp
-
创建一个 .NET 标准类库项目 MyClassLibrary
-
向类库添加
ISoundPlayer
接口:namespace MyClassLibrary { public interface ISoundPlayer { void PlaySound(); } }
-
在构造函数中添加一个获取 ISoundPlayer 接口的类:
using System; namespace MyClassLibrary { public class MyCLass { ISoundPlayer soundPlayer; public MyCLass(ISoundPlayer soundPlayer) { this.soundPlayer = soundPlayer ?? throw new ArgumentNullException(nameof(soundPlayer)); } public void DoSomething() { //Do something soundPlayer.PlaySound(); } } }
-
将 MyClassLibrary 的引用添加到您的 MyWpfApp。
-
创建一个实现 ISoundPlayerInterface 的 MySoundPlayer 类:
using MyClassLibrary; using System; using System.Windows.Media; namespace MyWpfApp { public class MySoundPlayer : ISoundPlayer { public void PlaySound() { //var player = new MediaPlayer(); //player.Open(new Uri("alert.mp3")); //player.Play(); //or simply System.Media.SystemSounds.Beep.Play(); } } }
-
在主窗口上放置一个按钮并处理其点击事件,实例化 MyClass 并将 MySoundPlayer 的实例传递给它。
private void button_Click(object sender,RoutedEventArgs e) { var myClass = new MyClassLibrary.MyCLass(new MySoundPlayer()); myClass.DoSomething(); }
注意
要实现 Inversion of Control,您可以考虑以下选项:
- 依赖注入:您可以依赖具有 PlaySound 方法的 ISoundPlayer 接口并将此依赖注入到您的库中。
- 事件:您可以在库中引发事件,让消费者订阅该事件并播放声音。
- 委托:您可能想要注入一个委托(作为属性或通过构造函数)并在您的库中使用该委托。