non-generic class members. for example, if myclass in code block 14 had a class member of type
string called m_name, you could write:
genericinfo.addvalue("m_name",m_name);
and:
m_name = genericinfo.getvalue<string>("m_name");
generics and remoting
you can define and deploy remote classes that utilize generics, and you can use programmatic or
administrative configuration. consider the class myserver that uses generics and is derived from
marshalbyrefobject:
public class myserver<t> : marshalbyrefobject
{...}
when using administrative type registration, you need to specify the exact types to use instead of the
generic type parameters. you must name the types in a language-neutral manner, and provide fully
qualified namespaces. for example, suppose the class myserver is defined in the namespace
remoteserver in the assembly serverassembly, and you want to use it with integer instead of the
generic type parameter t, in client activated mode. in that case, the required client-side type registration
entry in the configuration file would be:
<client url="...some url goes here...">
<activated
type="remoteserver.myserver[[system.int32]],serverassembly"/>
</client>
the matching host-side type registration entry in the configuration file is:
<service>
<activated
type="remoteserver.myserver[[system.int32]],serverassembly"/>
</service>
the double square brackets are used to specify multiple types. for example:
linkedlist[[system.int32],[system.string]]
when using programmatic configuration, you configure activation modes and type registration similar to
c# 1.1, except when defining the type of the remote object you have to provide specific types instead of
the generic type parameters. for example, for host-side activation mode and type registration you would
write:
type servertype = typeof(myserver<int>);
remotingconfiguration.registeractivatedservicetype(servertype);
for client-side type activation mode and location registration, you have the following:
type servertype = typeof(myserver<int>);
string url = ...; //some url initialization
remotingconfiguration.registerwellknownclienttype(servertype,url);
when instantiating the remote server, simply provide the specific types, just as if you where using a local
generic type:
myserver<int> obj;
obj = new myserver<int>();
//use obj
instead of using new, the client can optionally use the methods of the activator class to connect to
remote objects. when using activator.getobject() you need to provide the specific types to use, and
provide the specific types when explicitly casting the returned object:
string url = ...; //some url initialization
type servertype = typeof(myserver<int>);
myserver<int> obj;
obj = (myserver<int>)activator.getobject(servertype,url);
//use obj
the activator.createinstance() method has numerous overloaded versions. some of the versions can
be used with generic types:
type servertype = typeof(myserver<int>);
myserver<int> obj;
obj = (myserver<int>)activator.createinstance(servertype);
//use obj
however, for generic types you cannot use the versions of createinstance() and
createinstancefrom() that accept the type in string format and return objecthandle, such as:
public static objecthandle createinstance(string assemblyname,string
typename);
activator was designed without generics in mind, and it is therefore not completely type safe because
of the explicit cast from object. it is possible to compensate by defining the class genericactivator, as
shown in code block 15.
code block 15. the genericactivator
public class genericactivator
{
public static t createinstance<t>()
{
return (t)activator.createinstance(typeof(t));
}
public static t getobject<t>(string url)
{
return (t)activator.getobject(typeof(t),url);
}
}
genericactivator uses generic static methods to expose the most useful methods of activator. you
can use genericactivator instead of activator to activate generic and non-generic types. for example,
using getobject():
public class myserver : marshalbyrefobject
{...}
public class mygenericserver<t> : marshalbyrefobject
{...}
string url = ...;//some url initialization
myserver obj1 = genericactivator.getobject<myserver>(url);
mygenericserver obj2 = genericactivator.getobject<myserver<int>>(url);
or using createinstance():
myserver obj = genericactivator.createinstance<myserver>();
what generics cannot do
under .net 2.0, you cannot define generic web services. that is, web methods that use generic type
parameters. the reason is that none of the web service standards support generic services.