11using System ;
2+ using System . IO ;
3+ using System . Linq ;
4+ using System . Reflection ;
5+ using System . Collections . Generic ;
26
37namespace AutoUpdaterDotNET . ChangelogViewers ;
48
5- public static class ChangelogViewerFactory
9+ internal static class ChangelogViewerFactory
610{
7- public static IChangelogViewer Create ( ChangelogViewerType type )
11+ private static readonly List < IChangelogViewerProvider > Providers =
12+ [
13+ new RichTextBoxViewerProvider ( ) ,
14+ new WebBrowserViewerProvider ( )
15+ ] ;
16+
17+ static ChangelogViewerFactory ( )
18+ {
19+ if ( AutoUpdater . AutoLoadExtensions )
20+ LoadExtensions ( ) ;
21+ }
22+
23+ public static void RegisterProvider ( IChangelogViewerProvider provider )
24+ {
25+ if ( provider == null )
26+ throw new ArgumentNullException ( nameof ( provider ) ) ;
27+
28+ var providerType = provider . GetType ( ) ;
29+ var existingProvider = Providers . FirstOrDefault ( p => p . GetType ( ) == providerType ) ;
30+ if ( existingProvider != null )
31+ {
32+ if ( existingProvider . Priority == provider . Priority )
33+ return ; // Same type and priority, nothing to do
34+
35+ // Remove existing provider to allow priority override
36+ Providers . Remove ( existingProvider ) ;
37+ }
38+
39+ Providers . Add ( provider ) ;
40+ }
41+
42+ internal static IChangelogViewer Create ( IChangelogViewerProvider provider = null )
843 {
9- return type switch
44+ provider ??= AutoUpdater . ChangelogViewerProvider ;
45+
46+ if ( provider != null )
1047 {
11- ChangelogViewerType . RichTextBox => new RichTextBoxViewer ( ) ,
12- ChangelogViewerType . WebBrowser => new WebBrowserViewer ( ) ,
13- ChangelogViewerType . WebView2 when WebView2Viewer . IsAvailable ( ) => new WebView2Viewer ( ) ,
14- ChangelogViewerType . WebView2 => throw new InvalidOperationException ( "WebView2 runtime is not available" ) ,
15- _ => throw new ArgumentException ( $ "Unknown viewer type: { type } ")
16- } ;
48+ if ( ! provider . IsAvailable )
49+ throw new InvalidOperationException ( $ "The specified viewer provider '{ provider . GetType ( ) . Name } ' is not available in this environment.") ;
50+
51+ return provider . CreateViewer ( ) ;
52+ }
53+
54+ // Get all available providers ordered by priority (highest first)
55+ var availableProviders = Providers
56+ . Where ( p => p . IsAvailable )
57+ . OrderByDescending ( p => p . Priority ) ;
58+
59+ var changelogViewerProvider = availableProviders . FirstOrDefault ( ) ;
60+
61+ if ( changelogViewerProvider == null )
62+ throw new InvalidOperationException ( "No changelog viewers are available in this environment." ) ;
63+
64+ return changelogViewerProvider . CreateViewer ( ) ;
1765 }
1866
19- public static ChangelogViewerType GetDefaultViewerType ( )
67+ private static void LoadExtensions ( )
2068 {
21- if ( WebView2Viewer . IsAvailable ( ) )
22- return ChangelogViewerType . WebView2 ;
23-
24- return ChangelogViewerType . WebBrowser ;
69+ var extensions = Directory . GetFiles ( AppDomain . CurrentDomain . BaseDirectory , "AutoUpdater.NET.*.dll" ) ;
70+ if ( extensions . Length == 0 ) return ;
71+
72+ var iProviderType = typeof ( IChangelogViewerProvider ) ;
73+ foreach ( var extension in extensions )
74+ {
75+ try
76+ {
77+ var assembly = Assembly . LoadFrom ( extension ) ;
78+ var providers = assembly
79+ . GetTypes ( )
80+ . Where ( t => t . IsClass && ! t . IsAbstract && iProviderType . IsAssignableFrom ( t ) ) ;
81+
82+ foreach ( var provider in providers )
83+ {
84+ try
85+ {
86+ var instance = ( IChangelogViewerProvider ) Activator . CreateInstance ( provider ) ;
87+ if ( instance ? . IsAvailable == true )
88+ RegisterProvider ( instance ) ;
89+ }
90+ catch ( Exception ex )
91+ {
92+ System . Diagnostics . Debug . WriteLine ( $ "Failed to create instance of provider { provider . FullName } : { ex . Message } ") ;
93+ }
94+ }
95+ }
96+ catch ( Exception ex )
97+ {
98+ System . Diagnostics . Debug . WriteLine ( $ "Failed to load extension { extension } : { ex . Message } ") ;
99+ }
100+ }
25101 }
26102}
0 commit comments