Как установить производный объект в переменную базового класса, когда базовый класс является универсальным - PullRequest
1 голос
/ 01 декабря 2011

в своем приложении Silverlight 4 я пытаюсь использовать непатентованные средства, но есть еще одна проблема, которую я надеюсь решить с помощью stackoverflow-community:

У меня есть древовидная структура, которая может иметь два режима: режим редактора, в котором создается дерево, добавляются узлы, перемещаются, удаляются и т. Д., И режим конфигуратора, где пользователь может, например, выбирать узлы дерева. .

Чтобы представить дерево, я создал базовый класс для обоих режимов и производный класс для каждого режима. Поскольку в режиме редактора могут быть только узлы-редакторы, а в режиме конфигуратора могут быть только узлы-конфигураторы, я сделал базовый класс общим:

public abstract class ServiceModelBase<TRootNodeType>
    where TRootNodeType : ServiceNodeVMBase
{
  public TRootNodeType RootNode
  {
    get { return _rootNode; }
  }
  ...
}

public class ServiceModelConfigurator : ServiceModelBase<ServiceNodeVMConfigurator>
public class ServiceModelEditor : ServiceModelBase<ServiceNodeVMEditor>

И ServiceNodeVMConfigurator, и ServiceNodeVMEditor наследуют от ServiceNodeVMBase

Приложение может сохранять и загружать сохраненные данные. Загрузка работает (вкратце) следующим образом:
1.) Десериализовать сериализованные данные в специальный объект передачи данных.
2.) В зависимости от типа объекта передачи данных, создание ServiceModelConfigurator или ServiceModelEditor
3.) Запуск события, которое содержит (помимо прочего) созданную ServiceModel

Я создал класс, производный от EventArgs, который должен хранить ServiceModel. Поскольку эта ServiceModel может быть редактором или создателем, я объявил свойство для хранения его базового стиля:

public class ServiceModelLoadedEventArgs : EventArgs
{
  public ServiceModelBase<ServiceNodeVMBase> ServiceModel;
  ...
}

Но, к сожалению, я не могу присвоить производный ServiceModelEditor / Configurator переменной EventMgs ServiceModel:

ServiceModelLoadedEventArgs args = new ServiceModelLoadedEventArgs();
args.ServiceModel = new ServiceModelEditor();

Компилятор говорит мне, что он не может конвертировать ServiceModelEditor в ServiceModelBase

Может кто-нибудь сказать мне, как мне написать код для класса EventArgs, который я могу назначить ServiceModelEditor или ServiceModelConfigurator переменной ServiceModel?

PS: Я хочу извиниться, что это просто еще один вопрос, связанный с дженериками, но я боюсь, что дженерики и я еще не настоящие друзья.

Ответы [ 2 ]

1 голос
/ 01 декабря 2011

Чтобы использовать ковариацию, вам нужно объявить ковариантный интерфейс:

public interface IServiceModelBase<out TRootNode> 
     where TRootNode : ServiceNodeVMBase 
{ 
    TRootNode RootNode { get; }     
} 

public abstract class ServiceModelBase<TRootNode> : IServiceModelBase<TRootNode>
{
    ...
}

public class ServiceModelLoadedEventArgs : EventArgs   
{   
  public IServiceModelBase<ServiceNodeVMBase> ServiceModel { get; set; }  
  ...   
}   

public class ServiceModelEditor : ServiceModelBase<ServiceNodeVMEditor>  

И:

ServiceModelLoadedEventArgs args = new ServiceModelLoadedEventArgs();        
args.ServiceModel = new ServiceModelEditor();
0 голосов
/ 01 декабря 2011

Вы можете использовать ко-дисперсию :

public abstract class ServiceModelBase<out RootNodeType>
     where RootNodeType : ServiceNodeVMBase
{


}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...