2013-10-28 7 views
0

я получил здесь класс, который выглядит следующим образом:Преобразование объекта общего абстрактного класса

public abstract class SIBRegisterHardware2<T> : Register.IRegisterHardware<UInt16, UInt16> where T : IDevice 
{ 
    protected T open() 
    { 
     // connect to server and return device T 
    } 

    // .. 
} 

public class Device : SIBRegisterHardware2<IDevice> 
{ 
    // .. 
} 

и некоторые производные классы:

internal class DeviceA: SIBRegisterHardware2<IDeviceA> 
{ 
} 

internal class DeviceB: SIBRegisterHardware2<IDeviceB> 
{ 
} 

Сейчас я ищу решение, которое позволяет мне это:

if(createDevA == true) { 
    Device<IDevice> devHandle = new DeviceA(); 
} else { 
    Device<IDevice> devHandle = new DeviceB(): 
} 

дело в том, что такой код выдает ошибки так:

Cannot implicitly convert type 'DeviceA' to 'SIBRegisterHardware2<IDevice>' 

Есть ли способ, который позволил бы мне отрисовать шаблон таким образом?


Что-то я опробовал создает еще один класс, который работает с отражением:

public class DeviceX : SIBRegisterHardware2<IDevice> 
{ 
    private Register.IRegisterHardware<UInt16, UInt16> device = null; 
    private Type deviceType = null; 

    public DeviceX (String hwInterfaceClassName) 
    { 
     if (hwInterfaceClassName.Equals("DeviceA")) { 

      device = new DeviceA(); 
      deviceType = device.GetType(); 
     } 
     else if (hwInterfaceClassName.Equals("DeviceB")) { 

      device = new DeviceB(); 
      deviceType = device.GetType(); 
     } 
    } 

    public override String doSomething(int param) 
    { 
     return (String)deviceType.GetMethod("doSomething").Invoke(device, new object[] { param }); ; 
    } 
} 

но является то, что аккуратный дизайн?

+2

'' DeviceA' и DeviceB' не выводятся из 'Device'. Кроме того, 'Устройство' не является общим типом, и вы не можете записать' Device '. Я что-то пропустил? – Dennis

+0

спасибо за подсказку. Я добавил отсутствующий класс. – displayname

ответ

4

Вы должны использовать интерфейс вместо абстрактного класса для типа SIBRegisterHardware2. И чем вы можете использовать Covariance in Generics:

public interface IDevice { } 

public interface IDeviceA : IDevice { } 
public interface IDeviceB : IDevice { } 

public interface ISIBRegisterHardware2<out T> where T : class, IDevice 
{ 
    void DoSomething(); 
} 

internal class DeviceA : ISIBRegisterHardware2<IDeviceA> 
{ 
    //... 
} 

internal class DeviceB : ISIBRegisterHardware2<IDeviceB> 
{ 
    //... 
} 

if (createDevA == true) 
{ 
    ISIBRegisterHardware2<IDevice> devHandle = new DeviceA(); 
} 
else 
{ 
    ISIBRegisterHardware2<IDevice> devHandle = new DeviceB(); 
} 

UPDATE 0

public interface ISIBRegisterHardware2<out T> : Register.IRegisterHardware<UInt16, UInt16> where T : class, IDevice 
{ 
    T Open(); 
} 

public abstract class SIBRegisterHardware2<T> : ISIBRegisterHardware2<T> where T : class, IDevice 
{ 
    T ISIBRegisterHardware2<T>.Open() 
    { 
     return OpenInternal(); 
    } 

    protected virtual T OpenInternal() 
    { 
     //Common logic to open. 
    } 
} 

internal class DeviceA : SIBRegisterHardware2<IDeviceA> 
{ 
    //... 
} 

internal class DeviceB : SIBRegisterHardware2<IDeviceB> 
{ 
    //... 
} 

ISIBRegisterHardware2<IDevice> devHandle; 
if (createDevA == true) 
{ 
    devHandle = new DeviceA(); 
} 
else 
{ 
    devHandle = new DeviceB(); 
} 
devHandle.Open(); 
+0

Проблема здесь в том, что 'ISIBRegisterHardware2' не является« интерфейсом ». Это «абстрактный класс», который реализует несколько методов. – displayname

+0

Что мешает вам извлечь интерфейс из базового класса и работать с интерфейсом? –

+0

Есть методы, которые я хочу реализовать в 'ISIBRegisterHardware2', например. 'public T open()', который подключает программу к устройству, подключенному к компьютеру. Каждое устройство делает это одинаково. Единственное различие, конечно, это тип устройства, который возвращается (общий). – displayname

Смежные вопросы