Don't like ads? PRO users don't see any ads ;-)
Guest

Untitled

By: a guest on Apr 29th, 2012  |  syntax: None  |  size: 3.02 KB  |  hits: 14  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. How to cast generic interfaces using contravariant parameters to a base type?
  2. using System;
  3. using System.Diagnostics;
  4.  
  5. namespace ConsoleApplication2
  6. {
  7.     // Command classes
  8.  
  9.     public class CommandMessage
  10.     {
  11.         public DateTime IssuedAt { get; set; }
  12.     }
  13.  
  14.     public class CreateOrderMessage : CommandMessage
  15.     {
  16.         public string CustomerName { get; set; }
  17.     }
  18.  
  19.     // Covariant solution
  20.  
  21.     public interface ICommandMessageHandler1<out T> where T : CommandMessage
  22.     {
  23.         void Execute(CommandMessage command);
  24.     }
  25.  
  26.     public class CreateOrderHandler1 : ICommandMessageHandler1<CreateOrderMessage>
  27.     {
  28.         public void Execute(CommandMessage command)
  29.         {
  30.             // An explicit typecast is required
  31.             var createOrderMessage = (CreateOrderMessage) command;
  32.             Debug.WriteLine("CustomerName: " + createOrderMessage.CustomerName);
  33.         }
  34.     }
  35.  
  36.     // Contravariant attempt (doesn't work)
  37.  
  38.     public interface ICommandMessageHandler2<in T> where T : CommandMessage
  39.     {
  40.         void Execute(T command);
  41.     }
  42.  
  43.     public class CreateOrderHandler2 : ICommandMessageHandler2<CreateOrderMessage>
  44.     {
  45.         public void Execute(CreateOrderMessage command)
  46.         {
  47.             // Ideally, no typecast would be required
  48.             Debug.WriteLine("CustomerName: " + command.CustomerName);
  49.         }
  50.     }
  51.  
  52.     class Program
  53.     {
  54.         static void Main(string[] args)
  55.         {
  56.             var message = new CreateOrderMessage {CustomerName = "ACME"};
  57.  
  58.             // This code works
  59.             var handler1 = new CreateOrderHandler1();
  60.             ICommandMessageHandler1<CreateOrderMessage> handler1b = handler1;
  61.             var handler1c = (ICommandMessageHandler1<CommandMessage>) handler1;
  62.             handler1c.Execute(message);
  63.  
  64.             // This code throws InvalidCastException
  65.             var handler2 = new CreateOrderHandler2();
  66.             ICommandMessageHandler2<CreateOrderMessage> handler2b = handler2;
  67.             var handler2c = (ICommandMessageHandler2<CommandMessage>)handler2;  // throws InvalidCastException
  68.             handler2c.Execute(message);
  69.         }
  70.     }
  71. }
  72.        
  73. public class CommandMessage
  74. {
  75.     public DateTime IssuedAt
  76.     {
  77.         get;
  78.         set;
  79.     }
  80. }
  81.  
  82. public class CreateOrderMessage : CommandMessage
  83. {
  84.     public string CustomerName
  85.     {
  86.         get;
  87.         set;
  88.     }
  89. }
  90.  
  91. public interface ICommandMessageHandler2<in T> where T : CommandMessage
  92. {
  93.     void Execute(T command);
  94. }
  95. public class CreateOrderHandler2 : ICommandMessageHandler2<CreateOrderMessage>
  96. {
  97.     public void Execute(CreateOrderMessage command)
  98.     {
  99.         // No typecast is required
  100.         Debug.WriteLine("CustomerName: " + command.CustomerName);
  101.     }
  102. }
  103.  
  104. class Program
  105. {
  106.     static void Main(string[] args)
  107.     {
  108.         var message = new CreateOrderMessage
  109.         {
  110.             CustomerName = "ACME"
  111.         };
  112.  
  113.         // This code throws InvalidCastException
  114.         var handler2 = (ICommandMessageHandler2<CreateOrderMessage>)new CreateOrderHandler2();
  115.         handler2.Execute(message);
  116.     }
  117. }