-
-
Notifications
You must be signed in to change notification settings - Fork 49
Expand file tree
/
Copy pathAcknowledgementAttribute.cs
More file actions
175 lines (163 loc) · 7.19 KB
/
AcknowledgementAttribute.cs
File metadata and controls
175 lines (163 loc) · 7.19 KB
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
// Copyright (c) 2025 SIL Global
// This software is licensed under the MIT License (http://opensource.org/licenses/MIT)
using System;
using System.Diagnostics;
using System.IO;
namespace SIL.Acknowledgements
{
/// <summary>
/// If you add a "using SIL.Acknowledgements;" to your project's AssemblyInfo.cs file and
/// add an AcknowledgementAttribute for each dependency, then the AcknowledgementsProvider
/// will be able to collect your project's dependencies and display them in your project's SILAboutBox.
/// You just need to add the string #DependencyAcknowledgements# (probably surrounded by a <ul> element)
/// to your project's about box html file and the AcknowledgementsProvider will replace it
/// with each collected Acknowledgement set within a <li> element.
/// </summary>
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
public class AcknowledgementAttribute : Attribute
{
private string _html;
private string _copyright;
private string _name;
/// <summary>
/// Example Usage:
/// [assembly: Acknowledgement("Ionic.Zip.dll", Copyright = "Dino Chiesa", Url = "http://www.codeplex.com/DotNetZip",
/// LicenseUrl = "https://opensource.org/licenses/MS-PL", Location = "./Ionic.Zip.dll",
/// Html = "<li><a href='http://www.codeplex.com/DotNetZip'>Ionic.Zip</a> (MS-PL) by Dino Chiesa - a library for handling zip archives (Flavor=Retail)</li>")]
/// The above example provides a custom html. Leaving it out would generate the default html value.
/// See the Html property comment for the default value for this example.
/// Since the various optional properties of Acknowledgements have public setters, we only need a constructor
/// with one required parameter.
/// </summary>
public AcknowledgementAttribute(string key)
{
Key = key;
}
/// <summary>
/// Key should be something that will be unique and stable (as much as possible),
/// but not version-based, so we can eliminate duplicates. This is a required field.
///
/// For now, we are just using the Name of the Reference as listed in Visual Studio. In the .csproj file,
/// this can be found in the Include attribute of the Reference element up until the first comma.
/// </summary>
public string Key { get; }
/// <summary>
/// Acknowledgements will be sorted by Name. This string will show up in the default Html,
/// if no custom Html is set. This is an optional field.
/// If this property is set, it will override the automatic value produced by examining the dll itself.
/// </summary>
public string Name {
get
{
if (!string.IsNullOrEmpty(_name) || string.IsNullOrEmpty(Location))
return _name;
// Try to get it from the dll/exe file, failing that use the Key (which is almost always identical anyway).
var versionInfo = ExtractExecutableVersionInfo();
_name = versionInfo == null ? Key : versionInfo.ProductName;
return _name;
}
set => _name = value;
}
/// <summary>
/// An optional (but highly recommended!) Url that does one of the following:
/// - points to the source repo,
/// - points to a nuget package,
/// - points to the main project website.
/// If Url is provided and Html is not set, the default Html will create a link to this url
/// with the Name property as its label.
/// Thus, the primary goal is to be a URL that is a good starting point for someone who is
/// interested in learning more about this dependency
/// </summary>
public string Url { get; set; }
/// <summary>
/// An optional (but highly recommended!) Url that identifies the License under which we are using
/// the dependency (e.g. "https://opensource.org/licenses/MIT").
/// </summary>
public string LicenseUrl { get; set; }
/// <summary>
/// The name of the person or organization that holds the copyright to the code.
/// This is an optional field.
/// If this property is set, it will override the automatic value produced by examining the dll itself.
/// </summary>
public string Copyright
{
get
{
if (!string.IsNullOrEmpty(_copyright) || string.IsNullOrEmpty(Location))
return _copyright;
// Try to get it from the dll/exe file
var versionInfo = ExtractExecutableVersionInfo();
return versionInfo == null ? _copyright : versionInfo.LegalCopyright;
}
set => _copyright = value;
}
/// <summary>
/// If we can't find the file using the Location, return null.
/// Otherwise, returns the located executable file's FileVersionInfo.
/// </summary>
private FileVersionInfo ExtractExecutableVersionInfo()
{
try
{
return FileVersionInfo.GetVersionInfo(Location.Split(',')[0]);
}
catch (FileNotFoundException)
{
return null;
}
}
/// <summary>
/// The location gives the expected place in a client’s source tree where the dependency files would be found.
/// This is useful for making Linux copyright files. It can be a list (comma-separated).
/// Items may be relative to the client solution (e.g., something dependent on GeckoFx would specify
/// "packages/{filenames}", since that’s where Nuget will always put those files)
/// or relative to the DLL that has the acknowledgement attributes (e.g., SIL.Media.dll would specify
/// "./IrrKlang.dll, ./ikpFlac.dll, ./ikpMP3.dll", since we expect these DLLs to be downloaded somehow
/// to the same place in the project source tree as SIL.Media.dll itself).
/// If Name and/or Copyright are not specified, the code will use this Location field to find suitable substitutes
/// in the FileVersionInfo.
/// This is an optional field.
/// </summary>
public string Location { get; set; }
/// <summary>
/// If no custom Html is provided, this will generate a default <li></li> entry filled in with the information
/// provided in the acknowledgement.
///
/// Example default Html based on the example acknowledgement in the constructor comment is:
/// "<li><a href='http://www.codeplex.com/DotNetZip'>DotNetZip Library</a>: Dino Chiesa <a href='https://opensource.org/licenses/MS-PL'>https://opensource.org/licenses/MS-PL</a><li>"
///
/// Provide your own Html if you desire, for example, additional comments on a dependency to show up in a
/// consumer's SILAboutBox. Since each Acknowledgement's Html Property creates a <li> element by default, usually
/// your project's AboutBox html file would contain the SILAboutBox.DependencyMarker surrounded
/// by a <ul> element. This also means that usually you will want any custom Html to provide a surrounding <li> element.
/// </summary>
public string Html
{
get
{
if (!string.IsNullOrEmpty(_html))
return _html;
// Create a default html
_html = "<li>";
if (!string.IsNullOrEmpty(Name))
{
// If we have a Url, create a link, otherwise just use Name
_html += !string.IsNullOrEmpty(Url)
? "<a href='" + Url + "'>" + Name + "</a>"
: Name;
}
if (!string.IsNullOrEmpty(Copyright))
{
_html += ": " + Copyright;
}
if (!string.IsNullOrEmpty(LicenseUrl))
{
_html += " <a href='" + LicenseUrl + "'>" + LicenseUrl + "</a>";
}
_html += "</li>";
return _html ?? string.Empty;
}
set => _html = value;
}
}
}