* ActivationServices.cs: Added method for creating a proxy from a list
[mono.git] / mcs / class / corlib / System.Runtime.Remoting.Activation / ActivationServices.cs
1 //
2 // System.Runtime.Remoting.ActivationServices.cs
3 //
4 // Author: Lluis Sanchez Gual (lluis@ideary.com)
5 //
6 // (C) 2002, Lluis Sanchez Gual
7 //
8 \r
9 using System;\r
10 using System.Runtime.Remoting.Messaging;\r
11 using System.Runtime.Remoting.Activation;\r
12 using System.Runtime.Remoting.Contexts;\r
13 using System.Reflection;\r
14 using System.Runtime.CompilerServices;
15 using System.Collections;
16 using System.Runtime.Remoting.Channels;
17 \r
18 namespace System.Runtime.Remoting.Activation\r
19 {\r
20         internal class ActivationServices\r
21         {\r
22                 static IActivator _constructionActivator = new ConstructionLevelActivator ();\r
23 \r
24                 public static object CreateProxyFromAttributes (Type type, object[] activationAttributes)\r
25                 {\r
26                         string activationUrl = null;\r
27                         foreach (object attr in activationAttributes)
28                         {
29                                 if (!(attr is IContextAttribute)) throw new RemotingException ("Activation attribute does not implement the IContextAttribute interface");
30                                 if (attr is UrlAttribute) activationUrl = ((UrlAttribute)attr).UrlValue;
31                         }
32 \r
33                         if (activationUrl != null)
34                                 return RemotingServices.CreateClientProxy (type, activationUrl, activationAttributes);
35
36                         ActivatedClientTypeEntry activatedEntry = RemotingConfiguration.IsRemotelyActivatedClientType (type);
37                         if (activatedEntry != null)
38                                 return RemotingServices.CreateClientProxy (activatedEntry, activationAttributes);
39
40                         if (type.IsContextful)
41                                 return RemotingServices.CreateClientProxyForContextBound (type, activationAttributes);
42                         
43                         return null;
44                 }\r
45 \r
46                 public static ConstructionCall CreateConstructionCall (Type type, string activationUrl, object[] activationAttributes)
47                 {
48                         ConstructionCall ctorCall = new ConstructionCall (type);
49                         ctorCall.Activator = _constructionActivator;
50
51                         if (!type.IsContextful) return ctorCall;
52
53                         ArrayList attributes = new ArrayList ();
54                         if (activationAttributes != null) attributes.AddRange (activationAttributes);
55
56                         bool isContextOk = (activationUrl == ChannelServices.CrossContextUrl);  // Remote CBOs are always created in a new context
57                         Context currentContext = Threading.Thread.CurrentContext;
58
59                         if (isContextOk) \r
60                         {
61                                 foreach (IContextAttribute attr in attributes) \r
62                                 {
63                                         if (!attr.IsContextOK (currentContext, ctorCall)) \r
64                                         {
65                                                 isContextOk = false;
66                                                 break;
67                                         }
68                                 }
69                         }
70
71                         object[] typeAttributes = type.GetCustomAttributes (true);
72                         foreach (object attr in typeAttributes) \r
73                         {
74                                 if (attr is IContextAttribute) \r
75                                 {\r
76                                         isContextOk = isContextOk && ((IContextAttribute)attr).IsContextOK (currentContext, ctorCall);\r
77                                         attributes.Add (attr);
78                                 }
79                         }
80
81                         if (!isContextOk)
82                         {
83                                 // A new context is needed. Collect the context properties and set
84                                 // the context level activator.
85
86                                 ctorCall.SetActivationAttributes (attributes.ToArray());
87                                 ctorCall.Activator = new ContextLevelActivator (ctorCall.Activator);
88
89                                 foreach (IContextAttribute attr in attributes)
90                                         attr.GetPropertiesForNewContext (ctorCall);
91                         }
92
93                         return ctorCall;
94                 }\r
95 \r
96                 public static IMessage CreateInstanceFromMessage (IConstructionCallMessage ctorCall)\r
97                 {\r
98                         object obj = AllocateUninitializedClassInstance (ctorCall.ActivationType);\r
99                         ctorCall.MethodBase.Invoke (obj, ctorCall.Args);\r
100 \r
101                         ServerIdentity identity = (ServerIdentity) RemotingServices.GetMessageTargetIdentity (ctorCall);
102
103                         identity.AttachServerObject ((MarshalByRefObject) obj, Threading.Thread.CurrentContext);
104
105                         return new ConstructionResponse (obj, null, ctorCall);
106                 }\r
107 \r
108                 public static object CreateProxyForType (Type type)
109                 {
110                         // Called by the runtime when creating an instance of a type
111                         // that has been registered as remotely activated.
112
113                         // First of all check for remote activation. If the object is not remote, then
114                         // it may be contextbound.
115
116                         ActivatedClientTypeEntry activatedEntry = RemotingConfiguration.IsRemotelyActivatedClientType (type);
117                         if (activatedEntry != null)
118                                 return RemotingServices.CreateClientProxy (activatedEntry, null);
119
120                         WellKnownClientTypeEntry wellknownEntry = RemotingConfiguration.IsWellKnownClientType (type);
121                         if (wellknownEntry != null)
122                                 return RemotingServices.CreateClientProxy (wellknownEntry);
123
124                         if (type.IsContextful)
125                                 return RemotingServices.CreateClientProxyForContextBound (type, null);
126
127                         return null;
128                 }\r
129 \r
130                 // Allocates an uninitialized instance. It never creates proxies.\r
131                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
132                 private static extern object AllocateUninitializedClassInstance (Type type);
133 \r
134                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
135                 public extern static void EnableProxyActivation (Type type, bool enable);
136         }\r
137 }\r