generics - Covariance and contravariance usage in C# -
i'm trying achieve i'm not sure possible , i'm bit stuck.
i have base types called client , server defined this:
public class client { } public class server<clienttemplate> clienttemplate : client { public virtual void clientconnected(clienttemplate client){} public virtual void clientdisconnected(clienttemplate client){} public virtual void messagereceived(clienttemplate client, message message){} public virtual void sendmessage(clienttemplate client, message message){} }
these classes later expanded in different assembly this:
public class lobbyclient : client { string username; string passwordhash; } public class lobbyserver : server<lobbyclient> { public override void clientconnected(lobbyclient client) { console.writeline("client connected"); } }
from first assembly dynamically load second 1 base classes derived.
i'm trying this:
server<client> server = activator.createinstance(servertypeinfo);
but without luck conversion invalid.
i want later in code:
client client = activator.createinstance(clienttype) client; server.clientconnected(client);
i tried making further base interfaces iclient , iserver , derive client , server , setting template argument in did not work.
is there way in achieve goal here?
i see player.io (now yahoo games network) managed can't figure how code works looking @ compiled assembly.
https://gamesnet.yahoo.net/documentation/services/multiplayer/serverside
edit:
here version interfaces tried:
public interface iclient { } public class client : iclient { } interface iserver<in clienttemplate> clienttemplate : iclient { void clientconnected(clienttemplate client); void clientdisconnected(clienttemplate client); void messagereceived(clienttemplate client, message message); void sendmessage(clienttemplate client, message message); } public class server<clienttemplate> : iserver<clienttemplate> clienttemplate : iclient { public virtual void clientconnected(clienttemplate client){} public virtual void clientdisconnected(clienttemplate client){} public virtual void messagereceived(clienttemplate client, message message){} public virtual void sendmessage(clienttemplate client, message message){} }
and later in code:
iserver<iclient> server = activator.createinstance(servertypeinfo);
thank you
co- , contra-variance not work in case, attempting supply less derived parameter input implementation. also, co- contra-variance work via interfaces, have had type parameters declared in
or out
keywords.
for example (pseudo types here illustration):
iserver<client> server = new server<lobbyclient>(); client client = new gameclient(); server.clientconnected(client);
the server<lobbyclient>
cannot cast iserver<client>
, because expects input lobbyclient instances, interface potentially pass in any client
type.
there 2 ways can think of work around this, both involve subverting type system; need make sure types being used correct, else runtime exceptions.
the first method call server methods via reflection. can both quite slow , verbose, however.
the second method write non-generic interface server class, , have sever class explicitly implement it, while delegating each method corresponding generic implementation.
public interface iserver { void clientconnected(client client){} void clientdisconnected(client client){} void messagereceived(client client, message message){} void sendmessage(client client, message message){} } public class server<clienttemplate> : iserver clienttemplate : client { void iserver.clientconnected(client client) { clientconnected((clienttemplate)client); } void iserver.clientdisconnected(client client) { clientdisconnected((clienttemplate)client); } void iserver.messagereceived(client client, message message) { messagereceived((clienttemplate)client, message); } void iserver.sendmessage(client client, message message) { sendmessage((clienttemplate)client, message); } public virtual void clientconnected(clienttemplate client){} public virtual void clientdisconnected(clienttemplate client){} public virtual void messagereceived(clienttemplate client, message message){} public virtual void sendmessage(clienttemplate client, message message){} }
now, non-generic methods not show on server implementations when accessed directly, able assign instances iserver
interface , call non-generic methods. runtime exceptions if types not match correctly.
iserver server = activator.createinstance(servertypeinfo) iserver; client client = activator.createinstance(clienttype) client; server.clientconnected(client); // works
Comments
Post a Comment