forked from ClearCanvas/ClearCanvas
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPluginInfo.cs
221 lines (194 loc) · 6.68 KB
/
PluginInfo.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
#region License
// Copyright (c) 2013, ClearCanvas Inc.
// All rights reserved.
// http://www.clearcanvas.ca
//
// This file is part of the ClearCanvas RIS/PACS open source project.
//
// The ClearCanvas RIS/PACS open source project is free software: you can
// redistribute it and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// The ClearCanvas RIS/PACS open source project is distributed in the hope that it
// will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
// Public License for more details.
//
// You should have received a copy of the GNU General Public License along with
// the ClearCanvas RIS/PACS open source project. If not, see
// <http://www.gnu.org/licenses/>.
#endregion
using System;
using System.Collections.Generic;
using System.Reflection;
using ClearCanvas.Common.Utilities;
namespace ClearCanvas.Common
{
/// <summary>
/// Describes a plugin, and provides properties for querying the extension points and extensions defined
/// in the plugin.
/// </summary>
/// <remarks>
/// Instances of this class are immutable and safe for concurrent access by multiple threads.
/// </remarks>
[Serializable]
public sealed class PluginInfo : IBrowsable
{
/// <summary>
/// Internal method used by the framework to discover extension points and extensions declared in a plugin.
/// </summary>
/// <param name="asm"></param>
/// <param name="points"></param>
/// <param name="extensions"></param>
internal static void DiscoverExtensionPointsAndExtensions(Assembly asm, List<ExtensionPointInfo> points, List<ExtensionInfo> extensions)
{
foreach (var type in asm.GetTypes())
{
var epAttr = AttributeUtils.GetAttribute<ExtensionPointAttribute>(type, false);
if (epAttr != null)
{
if (IsValidExtensionPointClass(type))
{
points.Add(new ExtensionPointInfo(type, GetExtensionInterface(type), epAttr.Name, epAttr.Description));
}
else
{
Platform.Log(LogLevel.Error, SR.ExceptionExtensionPointMustSubclassExtensionPoint, type.FullName);
}
}
var attrs = AttributeUtils.GetAttributes<ExtensionOfAttribute>(type, false);
foreach (var a in attrs)
{
// is the extension a concrete class?
if (!IsConcreteClass(type))
{
Platform.Log(LogLevel.Error, SR.ExceptionExtensionMustBeConcreteClass, type.FullName);
continue;
}
var extensionPointClass = a.ExtensionPointClass;
if(!IsValidExtensionPointClass(extensionPointClass))
{
Platform.Log(LogLevel.Error, SR.ExceptionExtensionDoesNotExtendValidExtensionPointClass, type.FullName);
continue;
}
// does the extension implement the required interface?
var extensionInterface = GetExtensionInterface(extensionPointClass);
if (!extensionInterface.IsAssignableFrom(type))
{
Platform.Log(LogLevel.Error, SR.ExceptionExtensionDoesNotImplementRequiredInterface,
type.FullName,
extensionInterface);
continue;
}
extensions.Add(
new ExtensionInfo(
type,
extensionPointClass,
a.Name,
a.Description,
ExtensionSettings.Default.IsEnabled(type, a.Enabled),
a.FeatureToken
)
);
}
}
}
private static Type GetExtensionInterface(Type extensionPointClass)
{
if (!IsValidExtensionPointClass(extensionPointClass))
throw new ArgumentException(string.Format("{0} does not appear to be a valid extension point class.", extensionPointClass.FullName));
return extensionPointClass.BaseType.GetGenericArguments()[0];
}
private static bool IsValidExtensionPointClass(Type extensionPointClass)
{
var baseType = extensionPointClass.BaseType;
return baseType != null && baseType.IsGenericType && baseType.GetGenericTypeDefinition() == typeof(ExtensionPoint<>);
}
private static bool IsConcreteClass(Type type)
{
return !type.IsAbstract && type.IsClass;
}
private readonly string _name;
private readonly string _description;
private readonly string _icon;
private readonly AssemblyRef _assembly;
private readonly List<ExtensionPointInfo> _extensionPoints;
private readonly List<ExtensionInfo> _extensions;
/// <summary>
/// Internal constructor.
/// </summary>
internal PluginInfo(Assembly assembly, string name, string description, string icon)
: this(assembly, name, description, icon, new List<ExtensionPointInfo>(), new List<ExtensionInfo>())
{
DiscoverExtensionPointsAndExtensions(assembly, _extensionPoints, _extensions);
}
/// <summary>
/// Private constructor.
/// </summary>
private PluginInfo(Assembly assembly, string name, string description, string icon, List<ExtensionPointInfo> extensionPoints, List<ExtensionInfo> extensions)
{
_name = name;
_description = description;
_assembly = assembly;
_icon = icon;
_extensionPoints = extensionPoints;
_extensions = extensions;
}
/// <summary>
/// Gets the set of extensions defined in this plugin, including disabled and unlicensed extensions.
/// </summary>
public IList<ExtensionInfo> Extensions
{
get { return _extensions.AsReadOnly(); }
}
/// <summary>
/// Gets the set of extension points defined in this plugin.
/// </summary>
public IList<ExtensionPointInfo> ExtensionPoints
{
get { return _extensionPoints.AsReadOnly(); }
}
/// <summary>
/// Gets the assembly that implements this plugin.
/// </summary>
public AssemblyRef Assembly
{
get { return _assembly; }
}
/// <summary>
/// Gets the name of an icon resource to associate with the plugin.
/// </summary>
public string Icon
{
get { return _icon; }
}
public override string ToString()
{
return string.Format("{0} ({1})", _name ?? _assembly.Name, _assembly.Resolve().Location);
}
#region IBrowsable Members
/// <summary>
/// Formal name of this object, typically the type name or assembly name. Cannot be null.
/// </summary>
public string FormalName
{
get { return Assembly.Resolve().FullName; }
}
/// <summary>
/// Friendly name of the object, if one exists, otherwise null.
/// </summary>
public string Name
{
get { return _name; }
}
/// <summary>
/// A friendly description of this object, if one exists, otherwise null.
/// </summary>
public string Description
{
get { return _description; }
}
#endregion
}
}