Обычай mediatypeformatter не работающий над унаследованными классами

У меня есть эта линия:

GlobalConfiguration.Configuration.Formatters.Add(New ExcelMediaTypeFormatter(Of Classification)(Function(t) New ExcelRow(ExcelCell.Map(t.ChemicalAbstractService), ExcelCell.Map(t.Substance), ExcelCell.Map(t.Columns("Classifidcation")), ExcelCell.Map(t.Columns("Classification"))), Function(format) "excel"))

Это хорошо работает и создает excelfile из моего веб-API.

У меня есть несколько подклассов, который наследует этот класс Классификации, и я хочу сделать mediaformatter для каждого подкласса для получения определенных колонок в excelformatter. Проблемы - это, если мне действительно нравится это:

GlobalConfiguration.Configuration.Formatters.Add(New ExcelMediaTypeFormatter(Of CustomClassification)(Function(t) New ExcelRow(ExcelCell.Map(t.ChemicalAbstractService), ExcelCell.Map(t.Substance), ExcelCell.Map(t.Columns("Classifidcation")), ExcelCell.Map(t.Columns("Classification"))), Function(format) "excel"))

Тогда это не работает вообще. Это просто производит xml из стандартного средства форматирования вместо этого. Как я могу заставить его реагировать на подкласс, когда веб-API возвращает a

IQueryable(Of Classification)

Средство форматирования:

public class ExcelMediaTypeFormatter : BufferedMediaTypeFormatter 
    {
    private const string ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
    private readonly Func builder;

    public ExcelMediaTypeFormatter(Func value)
    {
        builder = value;
        SupportedMediaTypes.Add(new MediaTypeHeaderValue(ContentType));
    }

    public ExcelMediaTypeFormatter(Func value, params Func[] type)
        : this(value)
    {
        foreach (var mediaTypeMapping in type) {
            this.MediaTypeMappings.Add(Map(mediaTypeMapping));
        }
    }

    public override bool CanWriteType(Type type)
    {
        return type == typeof(IQueryable) || type == typeof(T); } public override bool CanReadType(Type type) { return false; } public override void WriteToStream(Type type, object value, Stream writeStream, HttpContent content) { using (Stream ms = new MemoryStream()) { using (var book = new ClosedXML.Excel.XLWorkbook()) { var sheet = book.Worksheets.Add("sample"); ICollection rows = type == typeof(IQueryable) ? ((IQueryable)value).ToList() : new List() { (T)value }; for (var r = 0; r < rows.Count; r++) { var result = builder((T)rows.ElementAt(r)); for (var c = 0; c < result.Count(); c++) { if (result.ElementAt(c) != null) sheet.Cell(r + 2, c + 1).Value = result.ElementAt(c).Value.ToString(); } } sheet.Columns().AdjustToContents(); book.SaveAs(ms); byte[] buffer = new byte[ms.Length]; ms.Position = 0; ms.Read(buffer, 0, buffer.Length); writeStream.Write(buffer, 0, buffer.Length); } } } 
0
nl ja de

1 ответы

CanWriteType will return false, because T is CustomClassification and type is Classification. Your formatter will not be used if it returns false.

Поскольку Классификацией является не обязательно CustomClassification , это не может работать.

Чтобы достигнуть, что вы хотите, необходимо изменить внедрение немного.

Ваш ExcelMediaTypeFormatter больше не будет универсален. И это не будет передано одно Func , но список IRowsBuilder случаи. Они будут использоваться в WriteToStream метод, чтобы выбрать правильного строителя:

public interface IRowsBuilder
{
    bool CanBuildFor(Type type);
    IEnumerable SupportedTypes { get; }
    ExcelRow BuildRow(object value);
}

public class RowsBuilder : IRowsBuilder where T : Classification
{
    Func _builder;

    public RowsBuilder(Func builder)
    {
        if(builder == null) throw new ArgumentNullException("builder");

        _builder = builder;
    }

    public bool CanBuildFor(Type type)
    {
        return type.IsSubclassOf(typeof(T));
    }

    public IEnumerable SupportedTypes
    {
        get { yield return typeof(T); }
    }

    public ExcelRow BuildRow(object value)
    {
        if(!CanBuildFor(value.GetType()))
            throw new ArgumentException();

        return _builder((T)value);
    }
}

public class ExcelMediaTypeFormatter : BufferedMediaTypeFormatter 
{
    private readonly ILookup _builder;

    public ExcelMediaTypeFormatter(IEnumerable builder)
    {
        _builder = builder.SelectMany(x => builder.SupportedTypes
                                                  .Select(y => new
                                                          {
                                                              Type = y,
                                                              Builder = x
                                                          }))
                          .ToLookup(x => x.Type, x => x.Builder); 
    }

    public override bool CanWriteType(Type type)
    {
        return type == typeof(IQueryable) ||
               type == typeof(Classification);
    }

   //...

    public override void WriteToStream(Type type, object value,
                                       Stream writeStream, HttpContent content)
    {

       //...

        List rows;
        if(type == typeof(IQueryable))
            rows = ((IQueryable)value).ToList();
        else
            rows = new List { (Classification)value };

        for (var r = 0; r < rows.Count; r++)
        {
            var value = rows.ElementAt(r);
            var builder = _builder[value.GetType()];
            var result = builder(value);
           //...
        }
    }
}

Вы теперь только зарегистрировали бы один ExcelMediaTypeFormatter со всеми строителями:

var customBuilder = new RowsBuilder(
                        t => new ExcelRow(ExcelCell.Map(t.ChemicalAbstractService),
                                          ExcelCell.Map(t.Substance), 
                                          ExcelCell.Map(t.Columns("Classifidcation")),
                                          ExcelCell.Map(t.Columns("Classification"))));
var builders = new List();
builder.Add(customBuilder);
builder.Add(someOtherBuilder);
var excelFormatter = new ExcelMediaTypeFormatter(builders, format => "excel");
GlobalConfiguration.Configuration
                   .Formatters
                   .Add(excelFormatter);
0
добавлено
@MichaelKireHansen: И где вы думаете, что те колонки прибывают из? Ваш веб-API возвращает Классификацию и не CustomClassification . Те колонки, как просто гарантируют, не будут там.
добавлено автор Daniel Hilgarth, источник
@MichaelKireHansen: Но как вы знали бы, что это - определенный подкласс? Снова: Ваш веб-API только возвращает базовый класс. Как вы знали бы, что это - определенный производный класс?
добавлено автор Daniel Hilgarth, источник
@MichaelKireHansen: Именно так я понимаю то, чего вы пытаетесь достигнуть: Ваш веб-метод API мог возвратить какой-либо из производных классов? И вы регистрируете средство форматирования для каждого из них, и вы хотите, чтобы средство форматирования для правильного производного класса использовалось?
добавлено автор Daniel Hilgarth, источник
@MichaelKireHansen: Как вы используете строителя ? У меня есть идея, как решить вашу проблему, но нуждаются, это ответило сначала.
добавлено автор Daniel Hilgarth, источник
@MichaelKireHansen: Нет, that' s действительно не чистый. Будьте так добры и покажите мне, как вы используете строителя в ExcelMediaTypeFormatter . Я тогда покажу вам более чистое решение.
добавлено автор Daniel Hilgarth, источник
@MichaelKireHansen: Пожалуйста, обновите свой вопрос с тем кодом. В каком методе это расположено?
добавлено автор Daniel Hilgarth, источник
@MichaelKireHansen: Я обновил свой ответ. Пожалуйста, проверьте.
добавлено автор Daniel Hilgarth, источник
У меня есть приблизительно 11 подклассов Классификации, где у них есть свои собственные колонки, и у превосходить учебного пособия должны быть различные колонки, соответствующие подклассу классификации. Я can' t помещают IList og колонки или что-то как этот в клетке непосредственно, таким образом, я didn' t знают, как получить все колонки (и свойства) для определенного подкласса, не делая mediatypeformatter для каждого подкласса
добавлено автор Michael Kire Hansen, источник
Я знаю, что, если это - определенный подкласс тогда, у этого есть некоторые определенные колонки , Отредактируйте: из причины я мог просто использовать Классификацию и вставить все возможные колонки, но это оставляет много внутри пустых столбцов превосхождение
добавлено автор Michael Kire Hansen, источник
Это - проблема:) Обычно это была бы возможная проверка это при помощи typeof. Также, где объект сделан, это сделано как CustomClassification и затем передано как Классификация, точно так же, как у вас может быть Список, но переданный как IList
добавлено автор Michael Kire Hansen, источник
Точно. Просто deguised как базовый класс
добавлено автор Michael Kire Hansen, источник
Я просто пробегаю каждый ряд и затем через колонки и добавляю их к превосходить странице. Получил его работающий посредством создания большого количества заявлений IIF (один для каждой возможной колонки, но не очень очевидный способ выполнения его
добавлено автор Michael Kire Hansen, источник
ICollection ряды = печатают == typeof (IQueryable )? ((IQueryable ) стоимость).ToList (): новый Список () {(T) стоимость}; для (вар r = 0; r <�ряды. Граф; r ++) {результат вара = строитель ((T) ряды. ElementAt(r)); для (вар c = 0; c <�результат. Граф (); C++) {если (результат. ElementAt (c)! = пустой указатель) лист. Клетка (r + 1, c + 1).Value = результат. ElementAt (c).Value. ToString (); }} почта Косяка, регулярная, к сожалению,
добавлено автор Michael Kire Hansen, источник
Я отредактировал свой оригинальный вопрос с кодом, где я использую строителя.
добавлено автор Michael Kire Hansen, источник
DotNetRuChat
DotNetRuChat
2 992 участник(ов)

Чат русскоязычного .NET сообщества http://dotnet.ru/ Вам могут быть интересны: @dotnetchat, @cilchat, @fsharp_chat, @pro_net, @xamarin_russia, @microsoftstackjobs, @uwp_ru Флуд в @dotnettalks

Microsoft Stack Jobs
Microsoft Stack Jobs
1 788 участник(ов)

Work & freelance only Microsoft Stack. Feed https://t.me/Microsoftstackjobsfeed Чат про F#: @Fsharp_chat Чат про C#: @CSharpChat Чат про Xamarin: @xamarin_russia Чат общения:@dotnettalks

pro.net
pro.net
710 участник(ов)

Обсуждение .NET Framework и всего, что с ним связано. Правила: не флудить не по теме, уважать ваших коллег и никакой рекламы (объявления о вакансиях можно согласовать с @AlexFails). Флудилка: @dotnettalks Участник @proDOT

Microsoft Developer Community Chat
Microsoft Developer Community Chat
584 участник(ов)

Чат для разработчиков и системных администраторов Microsoft Developer Community. __________ Новостной канал: @msdevru __________ Баним за: оскорбления, мат, рекламу, флуд, флейм, спам, NSFW контент, а также большое количество оффтоп тем. @banofbot

.NET Talks: Force Push Masters
.NET Talks: Force Push Masters
490 участник(ов)

Свободный чат .NET разработчиков. Правила: t.me/dotnettalks/56823 Вам могут быть интересны: @dotnetruchat, @dotnetchat, @cilchat, @fsharp_chat, @pro_net, @dotnetgroup, @xamarin_russia, @microsoftstackjobs, @uwp_ru http://combot.org/chat/-1001128250813

.NET Chat Убежище
.NET Chat Убежище
246 участник(ов)

Чат .NET разработчиков под эгидой MSK/SPB .NET Community Group Вам могут быть интересны: @fsharp_chat, @dotnetruchat, @cilchat, @xamarin_russia, @microsoftstackjobs, @dotnetgroup Флуд в @dotnettalks

.NET CIL Chat
.NET CIL Chat
54 участник(ов)

.NET CIL (aka IL aka MSIL)