3 // Copyright (c) Microsoft Corporation. All rights reserved.
6 /*============================================================
8 ** Purpose: Resource annotation rules.
10 ===========================================================*/
12 using System
.Diagnostics
;
13 using System
.Globalization
;
14 using System
.Runtime
.CompilerServices
;
16 using Microsoft
.Win32
;
17 using System
.Diagnostics
.Contracts
;
19 namespace System
.Runtime
.Versioning
21 [AttributeUsage(AttributeTargets
.Method
| AttributeTargets
.Property
| AttributeTargets
.Constructor
, Inherited
= false)]
22 [Conditional("RESOURCE_ANNOTATION_WORK")]
23 public sealed class ResourceConsumptionAttribute
: Attribute
25 private ResourceScope _consumptionScope
;
26 private ResourceScope _resourceScope
;
28 public ResourceConsumptionAttribute(ResourceScope resourceScope
)
30 _resourceScope
= resourceScope
;
31 _consumptionScope
= _resourceScope
;
34 public ResourceConsumptionAttribute(ResourceScope resourceScope
, ResourceScope consumptionScope
)
36 _resourceScope
= resourceScope
;
37 _consumptionScope
= consumptionScope
;
40 public ResourceScope ResourceScope
{
41 get { return _resourceScope; }
44 public ResourceScope ConsumptionScope
{
45 get { return _consumptionScope; }
49 [AttributeUsage(AttributeTargets
.Method
| AttributeTargets
.Field
| AttributeTargets
.Property
| AttributeTargets
.Constructor
, Inherited
= false)]
50 [Conditional("RESOURCE_ANNOTATION_WORK")]
51 public sealed class ResourceExposureAttribute
: Attribute
53 private ResourceScope _resourceExposureLevel
;
55 public ResourceExposureAttribute(ResourceScope exposureLevel
)
57 _resourceExposureLevel
= exposureLevel
;
60 public ResourceScope ResourceExposureLevel
{
61 get { return _resourceExposureLevel; }
66 // Default visibility is Public, which isn't specified in this enum.
67 // Public == the lack of Private or Assembly
68 // Does this actually work? Need to investigate that.
70 public enum ResourceScope
79 Private
= 0x10, // Private to this one class.
80 Assembly
= 0x20, // Assembly-level, like C#'s "internal"
85 internal enum SxSRequirements
90 CLRInstanceID
= 0x4, // for multiple CLR's within the process
95 public static class VersioningHelper
97 // These depend on the exact values given to members of the ResourceScope enum.
98 private const ResourceScope ResTypeMask
= ResourceScope
.Machine
| ResourceScope
.Process
| ResourceScope
.AppDomain
| ResourceScope
.Library
;
99 private const ResourceScope VisibilityMask
= ResourceScope
.Private
| ResourceScope
.Assembly
;
101 [System
.Security
.SecuritySafeCritical
]
102 [ResourceExposure(ResourceScope
.Process
)]
103 [MethodImpl(MethodImplOptions
.InternalCall
)]
104 private static extern int GetRuntimeId();
106 public static String
MakeVersionSafeName(String name
, ResourceScope
from, ResourceScope to
)
108 return MakeVersionSafeName(name
, from, to
, null);
111 [System
.Security
.SecuritySafeCritical
] // auto-generated
112 [ResourceExposure(ResourceScope
.None
)]
113 [ResourceConsumption(ResourceScope
.Process
, ResourceScope
.Process
)]
114 public static String
MakeVersionSafeName(String name
, ResourceScope
from, ResourceScope to
, Type type
)
116 ResourceScope fromResType
= from & ResTypeMask
;
117 ResourceScope toResType
= to
& ResTypeMask
;
118 if (fromResType
> toResType
)
119 throw new ArgumentException(Environment
.GetResourceString("Argument_ResourceScopeWrongDirection", fromResType
, toResType
), "from");
121 SxSRequirements requires
= GetRequirements(to
, from);
123 if ((requires
& (SxSRequirements
.AssemblyName
| SxSRequirements
.TypeName
)) != 0 && type
== null)
124 throw new ArgumentNullException("type", Environment
.GetResourceString("ArgumentNull_TypeRequiredByResourceScope"));
126 // Add in process ID, CLR base address, and appdomain ID's. Also, use a character identifier
127 // to ensure that these can never accidentally overlap (ie, you create enough appdomains and your
128 // appdomain ID might equal your process ID).
129 StringBuilder safeName
= new StringBuilder(name
);
130 char separator
= '_';
131 if ((requires
& SxSRequirements
.ProcessID
) != 0) {
132 safeName
.Append(separator
);
133 safeName
.Append('p');
135 safeName
.Append (NativeMethods
.GetCurrentProcessId ());
137 safeName
.Append(Win32Native
.GetCurrentProcessId());
140 if ((requires
& SxSRequirements
.CLRInstanceID
) != 0) {
141 String clrID
= GetCLRInstanceString();
142 safeName
.Append(separator
);
143 safeName
.Append('r');
144 safeName
.Append(clrID
);
146 if ((requires
& SxSRequirements
.AppDomainID
) != 0) {
147 safeName
.Append(separator
);
148 safeName
.Append("ad");
149 safeName
.Append(AppDomain
.CurrentDomain
.Id
);
151 if ((requires
& SxSRequirements
.TypeName
) != 0) {
152 safeName
.Append(separator
);
153 safeName
.Append(type
.Name
);
155 if ((requires
& SxSRequirements
.AssemblyName
) != 0) {
156 safeName
.Append(separator
);
157 safeName
.Append(type
.Assembly
.FullName
);
159 return safeName
.ToString();
162 private static String
GetCLRInstanceString()
164 int id
= GetRuntimeId();
165 return id
.ToString(CultureInfo
.InvariantCulture
);
168 private static SxSRequirements
GetRequirements(ResourceScope consumeAsScope
, ResourceScope calleeScope
)
170 SxSRequirements requires
= SxSRequirements
.None
;
172 switch(calleeScope
& ResTypeMask
) {
173 case ResourceScope
.Machine
:
174 switch(consumeAsScope
& ResTypeMask
) {
175 case ResourceScope
.Machine
:
179 case ResourceScope
.Process
:
180 requires
|= SxSRequirements
.ProcessID
;
183 case ResourceScope
.AppDomain
:
184 requires
|= SxSRequirements
.AppDomainID
| SxSRequirements
.CLRInstanceID
| SxSRequirements
.ProcessID
;
188 throw new ArgumentException(Environment
.GetResourceString("Argument_BadResourceScopeTypeBits", consumeAsScope
), "consumeAsScope");
192 case ResourceScope
.Process
:
193 if ((consumeAsScope
& ResourceScope
.AppDomain
) != 0)
194 requires
|= SxSRequirements
.AppDomainID
| SxSRequirements
.CLRInstanceID
;
197 case ResourceScope
.AppDomain
:
202 throw new ArgumentException(Environment
.GetResourceString("Argument_BadResourceScopeTypeBits", calleeScope
), "calleeScope");
205 switch(calleeScope
& VisibilityMask
) {
206 case ResourceScope
.None
: // Public - implied
207 switch(consumeAsScope
& VisibilityMask
) {
208 case ResourceScope
.None
: // Public - implied
212 case ResourceScope
.Assembly
:
213 requires
|= SxSRequirements
.AssemblyName
;
216 case ResourceScope
.Private
:
217 requires
|= SxSRequirements
.TypeName
| SxSRequirements
.AssemblyName
;
221 throw new ArgumentException(Environment
.GetResourceString("Argument_BadResourceScopeVisibilityBits", consumeAsScope
), "consumeAsScope");
225 case ResourceScope
.Assembly
:
226 if ((consumeAsScope
& ResourceScope
.Private
) != 0)
227 requires
|= SxSRequirements
.TypeName
;
230 case ResourceScope
.Private
:
235 throw new ArgumentException(Environment
.GetResourceString("Argument_BadResourceScopeVisibilityBits", calleeScope
), "calleeScope");
238 if (consumeAsScope
== calleeScope
) {
239 Contract
.Assert(requires
== SxSRequirements
.None
, "Computed a strange set of required resource scoping. It's probably wrong.");