从标准库播放 MediaPlayer

问题描述

从我的 .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 的范围)来使用它。

请按照以下步骤操作:

  1. 创建 WPF 应用程序 MyWpfApp

  2. 创建一个 .NET 标准类库项目 MyClassLibrary

  3. 向类库添加 ISoundPlayer 接口:

    namespace MyClassLibrary
    {
        public interface ISoundPlayer
        {
            void PlaySound();
        }
    }
    
  4. 在构造函数中添加一个获取 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();
            }
        }
    }
    
  5. 将 MyClassLibrary 的引用添加到您的 MyWpfApp。

  6. 创建一个实现 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();
            }
        }
    }
    
  7. 在主窗口上放置一个按钮并处理其点击事件,实例化 MyClass 并将 MySoundPlayer 的实例传递给它。

    private void button_Click(object sender,RoutedEventArgs e)
    {
        var myClass = new MyClassLibrary.MyCLass(new MySoundPlayer());
        myClass.DoSomething();
    }
    

注意

要实现 Inversion of Control,您可以考虑以下选项:

  • 依赖注入:您可以依赖具有 PlaySound 方法的 ISoundPlayer 接口并将此依赖注入到您的库中。
  • 事件:您可以在库中引发事件,让消费者订阅该事件并播放声音。
  • 委托:您可能想要注入一个委托(作为属性或通过构造函数)并在您的库中使用该委托。