2013-08-28 2 views
1

У меня есть абстрактный базовый класс под названием Rack, и у меня есть разные типы стеллажей, которые являются дочерними элементами стойки. Я хочу иметь возможность динамически генерировать общий объект C# для разных дочерних элементов класса Rack, чтобы вызвать правильный метод getData, в котором все дети имеют метод. Вот что я до сих пор.
Код ниже вызывает виртуальный метод в базовом классе Rack. Мне нужно, чтобы он вызывал методы в дочерних классах Rack.Dynamic Cast in C#

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Reflection; 

namespace IO_Interface 
{ 
class Channel 
{ 
    private object rack1; 
    private object rack2; 
    public Channel() 
    { 

    } 

    public Channel(object h1, object h2) 
    { 
     rack1 = h1; 
     rack2 = h2; 
    } 

    public void send() 
    { 

     Type rack1Info = rack1.GetType(); 
     Type rack2Info = rack2.GetType(); 
     string name = rack1.ToString(); 

     MethodInfo castMethod = rack1.GetType().GetMethod("getData").; 
     castMethod.Invoke(rack1.GetType(), null); 

    } 

} 
}` 
+0

Почему вы не можете просто напечатать 'rack1' и' rack2' как 'Rack' и напрямую вызовите метод getData'? – Lee

+0

Если это 'virtual', это все равно вызовет. Если это «новый», у вас есть проблема. –

+0

Динамическое литье невозможно на статически типизированном языке, таком как C#. Кажется, вам просто нужен «виртуальный» метод. – Jon

ответ

5

То, что вы хотите сделать, это объявить Rack1 и Rack2 как стойки, которая будет абстрактным классом с абстрактным методом GetData. Вы создадите их как дочерние классы Rack где-нибудь. Затем, когда вы вызываете GetData на стойке, он найдет переопределенный метод и вызовет его. Вот пример.

abstract class Rack 
{ 
    public abstract void GetData(); 
} 

class ChildRack1 : Rack 
{ 
    public override void GetData(){} 
} 

class ChildRack2 : Rack 
{ 
    public override void GetData(){} 
} 

class Channel 
{ 
    private Rack rack1; 
    private Rack rack2; 
    public Channel() 
    { 

    } 

    public Channel(Rack h1, Rack h2) 
    { 
     rack1 = h1; 
     rack2 = h2; 
    } 

    public void send() 
    { 

     rack1.GetData(); 
    } 

} 
+1

Стойка не должна быть «абстрактной» - это может быть обычный класс. 'GetData' просто должен быть' virtual', если он имеет базовую реализацию и 'abstract', если это не так. –

+0

Вы говорите, что когда метод send называется GetData будет знать, чтобы вызвать правильный дочерний метод? Когда я настраиваю конструктор, я посылаю ему двух детей из Rack. Я думал, что конструктор будет сбрасываться на базу и только вызывает виртуальный метод, но есть ли какое-то свойство объекта Rack, который все еще поддерживает свой дочерний тип? – OctopusPrime314

+0

GetType вернет тип дочернего элемента. Однако, если вы правильно отмечаете вещи как абстрактные/виртуальные и переопределяете их, тогда C# вызовет метод, который идет с типом, с которым он был создан. – Nikhil

0

Я думаю, что это обеспечит вам с реализацией вы хотите:

class Channel 
    { 
     private List<Rack> racks; 

     public Channel() 
     { 
      racks = new List<Rack>(); 
     } 

     public Channel(params Rack[] racks) 
     { 
      this.racks = racks.ToList(); 
     } 

     public void send() 
     { 
      foreach (Rack item in racks) 
      { 
       item.getData(); 
      } 

     } 

     public void SendSpecificRack(Rack rack) 
     { 
      //calls the getdata of the rack object passed 
      rack.getData(); 
     } 

    } 

    public class Rack 
    { 
     public virtual void getData() 
     { 
      Console.WriteLine("Base Rack"); 
     } 
    } 

    public class RackChild1 : Rack 
    { 
     public override void getData() 
     { 
      Console.WriteLine("RackChild1"); 
     } 
    } 

    public class RackChild2 : Rack 
    { 
     public override void getData() 
     { 
      Console.WriteLine("RackChild2"); 
     } 
    } 

Использование:

Channel chn = new Channel(new Rack[]{new RackChild1(),new RackChild2()}); 
chn.send(); 
RackChild2 rck = new RackChild2(); 
chn.SendSpecificRack(rck); 

Выход:

RackChild1 
RackChild2 
RackChild2