2006-01-02 Sebastien Pouliot <sebastien@ximian.com>
[mono.git] / mcs / class / corlib / System / Activator.cs
1 //
2 // System.Activator.cs
3 //
4 // Authors:
5 //   Nick Drochak II (ndrochak@gol.com)
6 //   Gonzalo Paniagua (gonzalo@ximian.com)
7 //
8 // (C) 2001 Nick Drochak II
9 // (c) 2002 Ximian, Inc. (http://www.ximian.com)
10 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 // 
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 // 
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //
31
32 using System.Globalization;
33 using System.Reflection;
34 using System.Runtime.Remoting;
35 using System.Runtime.Remoting.Activation;
36 using System.Runtime.CompilerServices;
37 using System.Runtime.InteropServices;
38 using System.Security.Permissions;
39 using System.Security.Policy;
40 using System.Configuration.Assemblies;
41
42 namespace System 
43 {
44         [ClassInterface (ClassInterfaceType.None)]
45 #if NET_2_0
46         [ComVisible (true)]
47         [ComDefaultInterface (typeof (_Activator))]
48 #endif
49         public sealed class Activator : _Activator
50         {
51                 const BindingFlags _flags = BindingFlags.CreateInstance | BindingFlags.Public | BindingFlags.Instance;
52                 const BindingFlags _accessFlags = BindingFlags.DeclaredOnly | BindingFlags.FlattenHierarchy | BindingFlags.IgnoreCase | 
53                                                                                         BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public |
54                                                                                         BindingFlags.Static;
55
56                 private Activator ()
57                 {
58                 }
59
60                 [MonoTODO]
61                 public static ObjectHandle CreateComInstanceFrom (string assemblyName, string typeName)
62                 {
63                         if (assemblyName == null)
64                                 throw new ArgumentNullException ("assemblyName");
65
66                         if (typeName == null)
67                                 throw new ArgumentNullException ("typeName");
68
69                         if (assemblyName.Length == 0)
70                                 throw new ArgumentException ("assemblyName");
71
72                         throw new NotImplementedException();
73                 }
74
75 #if NET_1_1
76                 [MonoTODO]
77                 public static ObjectHandle CreateComInstanceFrom (string assemblyName, string typeName,
78                                                                   byte []hashValue, AssemblyHashAlgorithm hashAlgorithm)
79                 {
80                         if (assemblyName == null)
81                                 throw new ArgumentNullException ("assemblyName");
82
83                         if (typeName == null)
84                                 throw new ArgumentNullException ("typeName");
85
86                         if (assemblyName.Length == 0)
87                                 throw new ArgumentException ("assemblyName");
88
89                         throw new NotImplementedException();
90                 }
91 #endif
92
93                 public static ObjectHandle CreateInstanceFrom (string assemblyFile, string typeName)
94                 {
95                         return CreateInstanceFrom (assemblyFile, typeName, null);
96                 }
97
98                 public static ObjectHandle CreateInstanceFrom (string assemblyFile, string typeName, object [] activationAttributes)
99                 {
100                         return Activator.CreateInstanceFrom (assemblyFile, typeName, false, _flags, null, null, null,
101                                 activationAttributes, null);
102                 }
103
104                 public static ObjectHandle CreateInstanceFrom (string assemblyFile, string typeName, bool ignoreCase,
105                                                                BindingFlags bindingAttr, Binder binder, object [] args,
106                                                                CultureInfo culture, object [] activationAttributes,
107                                                                Evidence securityInfo)
108                 {
109                         Assembly assembly = Assembly.LoadFrom (assemblyFile, securityInfo);
110                         if (assembly == null)
111                                 return null;
112
113                         Type type = assembly.GetType (typeName, true, ignoreCase);
114                         if (type == null)
115                                 return null;
116
117                         object obj = CreateInstance (type, bindingAttr, binder, args, culture, activationAttributes);
118                         return (obj != null) ? new ObjectHandle (obj) : null;
119                 }
120
121                 public static ObjectHandle CreateInstance (string assemblyName, string typeName)
122                 {
123                         if (assemblyName == null)
124                                 assemblyName = Assembly.GetCallingAssembly ().GetName ().Name;
125
126                         return Activator.CreateInstance (assemblyName, typeName, null);
127                 }
128
129                 public static ObjectHandle CreateInstance (string assemblyName, string typeName, object [] activationAttributes)
130                 {
131                         if (assemblyName == null)
132                                 assemblyName = Assembly.GetCallingAssembly ().GetName ().Name;
133
134                         return Activator.CreateInstance (assemblyName, typeName, false, _flags, null, null, null,
135                                 activationAttributes, null);
136                 }
137
138                 public static ObjectHandle CreateInstance (string assemblyName, string typeName, bool ignoreCase,
139                                                            BindingFlags bindingAttr, Binder binder, object [] args,
140                                                            CultureInfo culture, object [] activationAttributes, Evidence securityInfo)
141                 {
142                         Assembly assembly = null;
143                         if(assemblyName == null)
144                                 assembly = Assembly.GetCallingAssembly ();
145                         else
146                                 assembly = Assembly.Load (assemblyName, securityInfo);
147                         Type type = assembly.GetType (typeName, true, ignoreCase);
148                         object obj = CreateInstance (type, bindingAttr, binder, args, culture, activationAttributes);
149                         return (obj != null) ? new ObjectHandle (obj) : null;
150                 }
151
152 #if NET_2_0
153                 public static T CreateInstance <T> ()
154                 {
155                         return (T) CreateInstance (typeof (T));
156                 }
157 #endif
158
159                 public static object CreateInstance (Type type)
160                 {
161                         return CreateInstance (type, false);
162                 }
163
164                 public static object CreateInstance (Type type, params object [] args)
165                 {
166                         return CreateInstance (type, args, new object [0]);
167                 }
168
169                 public static object CreateInstance (Type type, object [] args, object [] activationAttributes)
170                 {
171                         CheckType (type);
172
173                         int length = 0;
174                         if (args != null)
175                                 length = args.Length;
176
177                         bool find_best = false;
178                         Type [] atypes = new Type [length];
179                         for (int i = 0; i < length; ++i) {
180                                 if (args [i] != null)
181                                         atypes [i] = args [i].GetType ();
182                                 else
183                                         find_best = true;
184                         }
185                         
186                         ConstructorInfo ctor = null;
187                         if (find_best)
188                                 ctor = FindBestCtor (type.GetConstructors (), atypes);
189                         else
190                                 ctor = type.GetConstructor (atypes);
191
192                         if (ctor == null) {
193                                 if (type.IsValueType && atypes.Length == 0)
194                                         return CreateInstanceInternal (type);
195
196                                 throw new MissingMethodException (Locale.GetText ("Constructor not found. Class") +
197                                                                 type.FullName);
198                         }
199
200                         CheckAbstractType (type);
201
202                         if (activationAttributes != null && activationAttributes.Length > 0) {
203                                 if (!type.IsMarshalByRef) {
204                                         string msg = Locale.GetText ("Type '{0}' doesn't derive from MarshalByRefObject.", type.FullName);
205                                         throw new NotSupportedException (msg);
206                                 }
207                                 object newOb = ActivationServices.CreateProxyFromAttributes (type, activationAttributes);
208                                 if (newOb != null)
209                                         return ctor.Invoke (newOb, args);
210                         }
211
212                         return ctor.Invoke (args);
213                 }
214
215                 public static object CreateInstance (Type type, BindingFlags bindingAttr, Binder binder, object [] args,
216                                                      CultureInfo culture)
217                 {
218                         return CreateInstance (type, bindingAttr, binder, args, culture, new object [0]);
219                 }
220
221                 public static object CreateInstance (Type type, BindingFlags bindingAttr, Binder binder, object [] args,
222                                                      CultureInfo culture, object [] activationAttributes)
223                 {
224                         CheckType (type);
225                 
226                         // It seems to apply the same rules documented for InvokeMember: "If the type of lookup
227                         // is omitted, BindingFlags.Public | BindingFlags.Instance will apply".
228                         if ((bindingAttr & _accessFlags) == 0)
229                                 bindingAttr |= BindingFlags.Public | BindingFlags.Instance;
230
231                         int length = 0;
232                         if (args != null)
233                                 length = args.Length;
234
235                         bool find_best = false;
236                         Type[] atypes = new Type [length];
237                         for (int i = 0; i < length; ++i) {
238                                 if (args [i] != null)
239                                         atypes [i] = args [i].GetType ();
240                                 else
241                                         find_best = true;
242                         }
243
244                         ConstructorInfo ctor = null;
245                         if (find_best)
246                                 ctor = FindBestCtor (type.GetConstructors (bindingAttr), atypes);
247                         else
248                                 ctor = type.GetConstructor (bindingAttr, binder, atypes, null);
249
250                         if (ctor == null) {
251                                 // Not sure about this
252                                 if (type.IsValueType && atypes.Length == 0) {
253                                         return CreateInstanceInternal (type);
254                                 }
255
256                                 throw new MissingMethodException (Locale.GetText ("Constructor not found. Class: ") +
257                                                                 type.FullName);
258                         }
259
260                         CheckAbstractType (type);
261
262                         if (activationAttributes != null && activationAttributes.Length > 0) {
263                                 if (!type.IsMarshalByRef) {
264                                         string msg = Locale.GetText ("Type '{0}' doesn't derive from MarshalByRefObject.", type.FullName);
265                                         throw new NotSupportedException (msg);
266                                 }
267                                 object newOb = ActivationServices.CreateProxyFromAttributes (type, activationAttributes);
268                                 if (newOb != null)
269                                         return ctor.Invoke (newOb, bindingAttr, binder, args, culture);
270                         }
271
272                         return ctor.Invoke (bindingAttr, binder, args, culture);
273                 }
274
275                 public static object CreateInstance (Type type, bool nonPublic)
276                 { 
277                         CheckType (type);
278                         CheckAbstractType (type);
279
280                         BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;
281                         if (nonPublic)
282                                 flags |= BindingFlags.NonPublic;
283
284                         ConstructorInfo ctor = type.GetConstructor (flags, null, CallingConventions.Any, Type.EmptyTypes, null);
285
286                         if (ctor == null) {
287                                 if (type.IsValueType)
288                                         return CreateInstanceInternal (type);
289
290                                 throw new MissingMethodException (Locale.GetText ("Default constructor not found."),
291                                                                 ".ctor() of " + type.FullName);
292                         }
293
294                         return ctor.Invoke (null);
295                 }
296
297                 private static void CheckType (Type type)
298                 {
299                         if (type == null)
300                                 throw new ArgumentNullException ("type");
301
302                         if ((type == typeof (TypedReference)) || (type == typeof (ArgIterator)) || (type == typeof (void)) ||
303                                 (type == typeof (RuntimeArgumentHandle))) {
304                                 string msg = Locale.GetText ("CreateInstance cannot be used to create this type ({0}).", type.FullName);
305                                 throw new NotSupportedException (msg);
306                         }
307                 }
308
309                 private static void CheckAbstractType (Type type)
310                 {
311                         if (type.IsAbstract) {
312                                 string msg = Locale.GetText ("Cannot create an abstract class '{0}'.", type.FullName);
313 #if NET_2_0
314                                 throw new MissingMethodException (msg);
315 #else
316                                 throw new MemberAccessException (msg);
317 #endif
318                         }
319                 }
320
321                 private static ConstructorInfo FindBestCtor (ConstructorInfo[] ctors, Type[] parameters)
322                 {
323                         foreach (ConstructorInfo ctor in ctors) {
324                                 ParameterInfo[] pis = ctor.GetParameters ();
325                                 if (parameters.Length != pis.Length)
326                                         continue;
327
328                                 bool full_match = true;
329                                 int i=0;
330                                 foreach (ParameterInfo pi in pis) {
331                                         if (parameters [i] == null)
332                                                 continue;
333                                         if (parameters [i] != pi.ParameterType) {
334                                                 full_match = false;
335                                                 break;
336                                         }
337                                 }
338
339                                 if (full_match)
340                                         return ctor;
341                         }
342                         return null;
343                 }
344
345                 [SecurityPermission (SecurityAction.LinkDemand, RemotingConfiguration = true)]
346                 public static object GetObject (Type type, string url)
347                 {
348                         if (type == null)
349                                 throw new ArgumentNullException ("type");
350
351                         return RemotingServices.Connect (type, url);
352                 }
353
354                 [SecurityPermission (SecurityAction.LinkDemand, RemotingConfiguration = true)]
355                 public static object GetObject (Type type, string url, object state)
356                 {
357                         if (type == null)
358                                 throw new ArgumentNullException ("type");
359
360                         return RemotingServices.Connect (type, url, state);
361                 }
362
363                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
364                 internal static extern object CreateInstanceInternal (Type type);
365
366 #if NET_1_1
367                 void _Activator.GetIDsOfNames ([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
368                 {
369                         throw new NotImplementedException ();
370                 }
371
372                 void _Activator.GetTypeInfo (uint iTInfo, uint lcid, IntPtr ppTInfo)
373                 {
374                         throw new NotImplementedException ();
375                 }
376
377                 void _Activator.GetTypeInfoCount (out uint pcTInfo)
378                 {
379                         throw new NotImplementedException ();
380                 }
381
382                 void _Activator.Invoke (uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams,
383                         IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
384                 {
385                         throw new NotImplementedException ();
386                 }
387 #endif
388         }
389 }