2013-10-26 2 views
3

Я пытаюсь применить некоторый тип к другому родовому типу, но я не могу найти какое-либо решение, как это можно сделать в моем конкретном ситуация. Упрощенная ситуация такова. Обратите внимание, что это может показаться очень странным и искусственным, но это просто указывает на мою проблему. Фактическое применение имеет смысл ... :-)Явно бросаю объект на другой объект общего типа в C#, который доступен только во время выполнения

// Raw data coming from some source 
public class RawDataType { }  

// Abstract base class for structured data representing this raw data 
public abstract class AbstractListDataType { } 

// Generates lists of structured data 
public class ListGenerator<TListDataType> where TListDataType : AbstractListDataType 
{ 
    public List<TListDataType> GenerateList() 
    { 
     // Get the data from some mysterious place 
     RawDataType data = new RawDataType() { ... } 
     // Cast it to the required structured data type 
     return new List<TListDataType>() { data as TListDataType ??? } 
    } 
} 

Затем в другого узел, который загружается в выполнении, есть некоторые конкретные представления для этого исходных данных. Сам ListGenerator абсолютно не знает об этих типах. После того, как сборка, содержащая структурированные типы данных, была загружена, она проверяется с отражением, чтобы увидеть, какие типы структурированных данных могут быть сгенерированы.

// Two types of structured application data that can be created from the raw data 
public class ListDataTypeA : AbstractListDataType 
{ 
    public static explicit operator ListDataTypeA(RawDataType data) { ... } 
} 
public class ListDataTypeB : AbstractListDataType 
{ 
    public static explicit operator ListDataTypeB(RawDataType data) { ... } 
} 

Конечно,

data as TListDataType 

не имеет смысла. Как я могу добиться динамического переноса из RawDataType, то есть ListDataTypeA, для которого я знаю, что существует явное преобразование, которое доступно, но только во время выполнения?

Edit:

кажется следующее работает:

(TListDataType)(dynamic)data 

Я нахожу это очень некрасиво. Учитывая ситуацию, которую я описал здесь, есть ли лучший способ?

+2

Это может выглядят уродливыми, но это имеет прекрасный смысл, учитывая то, что происходит под капотом. Вероятно, это выглядело бы менее уродливым, если бы «данные» были «динамическими» с самого начала. –

+0

Это, в основном, то, что DLR для ... Следуйте советам @RobertHarvey, и вам должно быть хорошо идти. – Haney

ответ

1

Если dynamic подходит вам не подходит - попробуйте ввести более стандартный шаблон завода.

Поскольку явное литье разрешено во время компиляции, вам придется вручную вызвать этот метод вручную (то есть через отражение).

я бы другой маршрут и добавить метод «Load», чтобы AbstractListDataType или иметь фабричный метод/класс для создания элементов желаемого класса:

public abstract class AbstractListDataType { 
    public void Load(RawData data).... 
} 

public class ListGenerator<TListDataType> 
    where TListDataType : AbstractListDataType, new() 

    public List<TListDataType> GenerateList() 
    { 
     RawDataType data = new RawDataType() { ... } 
     var item = new T(); 
     item.Load(data); 
     return new List<TListDataType>() { item }; 
    } 
} 

Или завод подход:

public abstract class ListItemFactory<T> 
{ 
     abstract public T CreateFromRawData(RawDataType data); 
} 

public class ListGenerator<TListDataType> 
    where TListDataType : AbstractListDataType 
{ 
    ListItemFactory<TListDataType> factory; 
    public ListGenerator<TListDataType>(ListItemFactory<TListDataType> factory) 
    { 
     this.factory = factory; 
    } 

    public List<TListDataType> GenerateList() 
    { 
     RawDataType data = new RawDataType() { ... } 
     return new List<TListDataType>() { factory.CreateFromRawData(data)}; 
    } 
} 
Смежные вопросы