使用一种中间模型

Use a sort of Intermediate models

我正在编写一个在不同流媒体服务之间同步播放列表的程序,问题是每个服务使用不同的结构和功能。 我想做到 "modular" 这样我就可以添加新服务并将它们与其他服务同步,而无需为我已经在应用程序中的每项服务对它们进行编程,我想到的最好的想法是通过使用排序来实现它中间语言(或中间模型),例如

namespace Service1
{
    class Service1Album
    {
        public string ID { get; set; } 
        public Service1Artist Artist { get; set; }
        //Some other props...

        public IntermediateAlbum ToIntermediate()
        {
            //conversion...
        }
    }
    class Service1Artist
    {
        //Some props...
        public string ID { get; set; }
        public IntermediateArtist ToIntermediate()
        {
            //conversion...
        }
    }
}
namespace Intermediate
{
    class IntermediateArtist
    {
        //Props that every service has in common...
    }
    class IntermediateAlbum
    {
        //Props that every service has in common...
    }
}

通过这种方式,我实现的每个服务都接受作为其函数中间模型的参数并输出他自己的可以转换的模型。

Service1Album album = service1.GetAllAlbums()[0];
IntermediateAlbum intermediateAlbum = album.ToIntermediate();
service2.AddAlbum(intermediateAlbum);
service3.AddAlbum(intermediateAlbum);

有什么方法可以更优雅地实现它吗?如果是这样,有没有一种方法可以从像这样抽象每个服务的 ServiceContainer 继承每个服务?

var sList = new List<ServiceContainer>{};
sList.Add(new Service1());
sList.Add(new Service2());
foreach (var service in sList)
{
    service.addAlbum(new IntermediateAlbum()
                          {
                             //properties
                          });
}

卢卡 - 欢迎!您正在发现代码中需要一些设计模式。这真的很棒 - 这意味着事情变得非常复杂,您可以开始依赖其他人花费数年时间改进的模式来构建您的解决方案。

#1 - 切换到使用接口 + 设计模式

如果我是你,我会首先将所有内容抽象为接口(例如 - 你会 运行 你在每个服务中针对 IAlbum 和 IArtist 的工作,而不是具体的实现)。

然后,一旦您的界面就位,请查看 gang-of-four patterns 的 .net 代码以了解如何布局工作。

#2 - 基础知识

有很多代码要写,但骨架最终可能看起来像这样

namespace MusicService
{
    public interface IAlbum {
        //common album properties/methods
    }
    public interface IArtist {
        //common artist properties/methods
    }
    internal abstract class AlbumBase:IAlbum {
        // implement common functions and properties if you have them...
        // otherwise, skip this
    }
    internal abstract class ArtistBase:IAlbum {
        // implement common functions and properties if you have them...
        // otherwise, skip this
    }   
}

namespace MusicService.AppleMusic 
{
    internal class Album:AlbumBase 
    {  //OR Album:IAlbum if you skipped that AlbumBase thing
        //code apple music specific stuff here ... 
        // think of this as a "mask" that the apple album is 
        // wearing so that it can pretend to be an iAlbum
    }
    internal class Artist:ArtistBase 
    {  
        //same comments apply here
    }   
}
namespace MusicService.Spotify 
{
    internal class Album:AlbumBase 
    {  
        //GO and do liekwise with Spotify
    }
    internal class Artist:ArtistBase 
    {  
        //GO and do liekwise with Spotify
    }
}

#3 - 实现实际的 SYNC

既然您已经有了各种音乐服务所需的代码(排列整齐,这样您的程序员同事就不必绞尽脑汁就能弄清楚您在想什么),您可以编写 SyncService 代码了。

我不想破坏乐趣(同步服务可以使用 decorator pattern or it could be a sort of composite -- 不确定您的同步代码需要做什么),但您的最终同步代码可以像以下一样简单:

var myService = new SyncService();
myService.AddAppleMusic();
myService.AddSpotify();
myService.Sync();

破坏乐趣

好的。美好的。这就是我要做的。

namespace MusicService {
    public interface IService {
        //propably a List<IAlbum> and List<IA> somewhere in here
        void Sync();
    }

    public class SyncService {
        internal List<IService> _services;

        public void AddService(IService musicService) {
            if(_services==null){_services=new List<IService>();}
            _services.Add(musicService);
        }

        public void Sync() {
            foreach(IService ms in _services) {
                ms.Sync();
            }
        }
    }
}

namespace MusicService.AppleMusic {
    internal AppleSyncService:IService {
        public AppleSyncService() {
            //Do your apple-specific initializations here
        }
        public void Sync() {
            //apple-sync
        }
    }

    internal class ExtendService(){
        public static void AddAppleMusic(this SyncService syncAgent) {
           syncAgent.AddService(new AppleSyncService());
        }            
    }
}

显然 - none 的代码可以编译,并且在记事本中编码可能不是一个好主意。但是,它为您提供了上面示例代码的基于模式的替代方案。并且 - 如果您添加第三个音乐服务,您就不会 运行 打破 apple 和 spotify 的风险只是为了加入那个新服务!

祝你好运。听起来是个有趣的项目。