ReportViewer 2010 борется с полиморфизмом - PullRequest
1 голос
/ 31 марта 2011

У меня есть отчет rdlc, который принимает в качестве источника данных ReportDataSource List<BaseClass>. BaseClass имеет два производных класса A и B.
В отчете я группирую на основе свойства базового класса. Пока список содержит только объекты A или B, все работает нормально. Однако, если я смешиваю экземпляры из A и B, создание отчета завершается неудачно со следующим сообщением:

Выражение группы, используемое в группировке «[Имя группы]», ссылается на поле набора данных, содержащее ошибку: FieldValueException

Свойство возвращает для обоих классов простой строковый литерал, поддерживаемый константой классов, в этом нет ничего плохого. Я также проверил все остальные используемые свойства, но с ними все в порядке.
Кто-нибудь еще видел такое поведение или у кого-то есть объяснение этому поведению? Мне кажется, что средство просмотра отчетов не любит полиморфизм! Может ли это быть?

Пример * * тысяча двадцать-один

public abstract class BaseClass{
   public abstract string GroupKey{get;}
}
public class A : BaseClass{
    public override string GroupKey{
       get{
          return ...
       }
    }
}
public class B : BaseClass{
    public override string GroupKey{
       get{
          return ...
       }
    }
}

1 Ответ

3 голосов
/ 31 марта 2011

Оказалось, что это еще одно ограничение Report Viewer. В качестве решения я создал класс C, который также является производным от BaseClass и содержит экземпляр BaseClass.
Прежде чем предоставить мой List<BaseClass> в качестве источника данных для средства просмотра отчетов, я обертываю все содержащиеся в нем экземпляры A и B с экземпляром C и передаю список C в средство просмотра отчетов. Поэтому все экземпляры одного типа, и программа просмотра отчетов довольна.

Вот пример. Я надеюсь, что это помогает кому-то в той же ситуации:

public abstract class BaseClass{
   public string GroupKey{get;}
   public virtual C GetWorkaroundWrapper(){
       return new C(this);
   }
}
public class A : BaseClass{
    public override string GroupKey{
       get{
          return ...
          }
    }
}
public class B : BaseClass{
    public override string GroupKey{
       get{
          return ...
          }
    }
}
public class C : BaseClass{
    BaseClass m_baseClass;
    public C(BaseClass baseClass){
         if(null == baseClass){
             throw new ArgumentNullException("baseClass");
         }
         m_baseClass=baseClass;
    }
    public override string GroupKey{
         get{
             return m_baseCLass.GroupKey;
         }
    }
    public override C GetWorkaroundWrapper(){
         return this;
    }
}

GetWorkaroundWrapper -Методис только для удобства. При этом создание оболочки упрощается:

List<C> workaroundList=new List<C>();
foreach(BaseClass item in sourceList){
 workaroundList.Add(item.GetWorkaroundWrapper());
}

dataSource.Value=workaroundList;

Обратите внимание, что не важно, что список имеет C. Он также работает со списком BaseClass, но более удобно использовать список C.

...