Fix warnings, improve performance (#1665)

* Fix warnings, improve performance

`QueryResult.Items` is now a `IReadOnlyList` so we don't need to
allocate a new `Array` when we have a `List` (and `Items` shouldn't need to
be mutable anyway)

* Update Providers .csproj to latest C#

* Remove extra newline from DtoService.cs

* Remove extra newline from UserLibraryService.cs
This commit is contained in:
Bond-009 2019-09-02 08:19:29 +02:00 committed by Anthony Lavado
parent cb393c215a
commit ee637e8fec
37 changed files with 308 additions and 218 deletions

View file

@ -289,7 +289,7 @@ namespace Emby.Dlna.ContentDirectory
var childrenResult = GetUserItems(item, serverItem.StubType, user, sortCriteria, start, requestedCount); var childrenResult = GetUserItems(item, serverItem.StubType, user, sortCriteria, start, requestedCount);
totalCount = childrenResult.TotalRecordCount; totalCount = childrenResult.TotalRecordCount;
provided = childrenResult.Items.Length; provided = childrenResult.Items.Count;
foreach (var i in childrenResult.Items) foreach (var i in childrenResult.Items)
{ {
@ -309,6 +309,7 @@ namespace Emby.Dlna.ContentDirectory
} }
} }
} }
writer.WriteFullEndElement(); writer.WriteFullEndElement();
//writer.WriteEndDocument(); //writer.WriteEndDocument();
} }
@ -386,7 +387,7 @@ namespace Emby.Dlna.ContentDirectory
totalCount = childrenResult.TotalRecordCount; totalCount = childrenResult.TotalRecordCount;
provided = childrenResult.Items.Length; provided = childrenResult.Items.Count;
var dlnaOptions = _config.GetDlnaConfiguration(); var dlnaOptions = _config.GetDlnaConfiguration();
@ -677,7 +678,7 @@ namespace Emby.Dlna.ContentDirectory
return new QueryResult<ServerItem> return new QueryResult<ServerItem>
{ {
Items = list.ToArray(), Items = list,
TotalRecordCount = list.Count TotalRecordCount = list.Count
}; };
} }
@ -755,7 +756,7 @@ namespace Emby.Dlna.ContentDirectory
return new QueryResult<ServerItem> return new QueryResult<ServerItem>
{ {
Items = list.ToArray(), Items = list,
TotalRecordCount = list.Count TotalRecordCount = list.Count
}; };
} }
@ -860,7 +861,7 @@ namespace Emby.Dlna.ContentDirectory
return new QueryResult<ServerItem> return new QueryResult<ServerItem>
{ {
Items = list.ToArray(), Items = list,
TotalRecordCount = list.Count TotalRecordCount = list.Count
}; };
} }

View file

@ -247,7 +247,7 @@ namespace Emby.Server.Implementations.Activity
ReadTransactionMode); ReadTransactionMode);
} }
result.Items = list.ToArray(); result.Items = list;
return result; return result;
} }

View file

@ -2746,7 +2746,7 @@ namespace Emby.Server.Implementations.Data
var returnList = GetItemList(query); var returnList = GetItemList(query);
return new QueryResult<BaseItem> return new QueryResult<BaseItem>
{ {
Items = returnList.ToArray(), Items = returnList,
TotalRecordCount = returnList.Count TotalRecordCount = returnList.Count
}; };
} }
@ -2883,7 +2883,7 @@ namespace Emby.Server.Implementations.Data
} }
LogQueryTime("GetItems", commandText, now); LogQueryTime("GetItems", commandText, now);
result.Items = list.ToArray(); result.Items = list;
return result; return result;
} }
@ -3161,7 +3161,7 @@ namespace Emby.Server.Implementations.Data
var returnList = GetItemIdsList(query); var returnList = GetItemIdsList(query);
return new QueryResult<Guid> return new QueryResult<Guid>
{ {
Items = returnList.ToArray(), Items = returnList,
TotalRecordCount = returnList.Count TotalRecordCount = returnList.Count
}; };
} }
@ -3281,7 +3281,7 @@ namespace Emby.Server.Implementations.Data
LogQueryTime("GetItemIds", commandText, now); LogQueryTime("GetItemIds", commandText, now);
result.Items = list.ToArray(); result.Items = list;
return result; return result;
} }
@ -5520,7 +5520,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
result.TotalRecordCount = list.Count; result.TotalRecordCount = list.Count;
} }
result.Items = list.ToArray(); result.Items = list;
return result; return result;
} }

View file

@ -80,27 +80,25 @@ namespace Emby.Server.Implementations.Dto
return GetBaseItemDto(item, options, user, owner); return GetBaseItemDto(item, options, user, owner);
} }
public BaseItemDto[] GetBaseItemDtos(IReadOnlyList<BaseItem> items, DtoOptions options, User user = null, BaseItem owner = null) /// <inheritdoc />
=> GetBaseItemDtos(items, items.Count, options, user, owner); public IReadOnlyList<BaseItemDto> GetBaseItemDtos(IReadOnlyList<BaseItem> items, DtoOptions options, User user = null, BaseItem owner = null)
public BaseItemDto[] GetBaseItemDtos(IEnumerable<BaseItem> items, int itemCount, DtoOptions options, User user = null, BaseItem owner = null)
{ {
var returnItems = new BaseItemDto[itemCount]; var returnItems = new BaseItemDto[items.Count];
var programTuples = new List<Tuple<BaseItem, BaseItemDto>>(); var programTuples = new List<(BaseItem, BaseItemDto)>();
var channelTuples = new List<Tuple<BaseItemDto, LiveTvChannel>>(); var channelTuples = new List<(BaseItemDto, LiveTvChannel)>();
var index = 0; for (int index = 0; index < items.Count; index++)
foreach (var item in items)
{ {
var item = items[index];
var dto = GetBaseItemDtoInternal(item, options, user, owner); var dto = GetBaseItemDtoInternal(item, options, user, owner);
if (item is LiveTvChannel tvChannel) if (item is LiveTvChannel tvChannel)
{ {
channelTuples.Add(new Tuple<BaseItemDto, LiveTvChannel>(dto, tvChannel)); channelTuples.Add((dto, tvChannel));
} }
else if (item is LiveTvProgram) else if (item is LiveTvProgram)
{ {
programTuples.Add(new Tuple<BaseItem, BaseItemDto>(item, dto)); programTuples.Add((item, dto));
} }
if (item is IItemByName byName) if (item is IItemByName byName)
@ -121,7 +119,6 @@ namespace Emby.Server.Implementations.Dto
} }
returnItems[index] = dto; returnItems[index] = dto;
index++;
} }
if (programTuples.Count > 0) if (programTuples.Count > 0)
@ -140,33 +137,32 @@ namespace Emby.Server.Implementations.Dto
public BaseItemDto GetBaseItemDto(BaseItem item, DtoOptions options, User user = null, BaseItem owner = null) public BaseItemDto GetBaseItemDto(BaseItem item, DtoOptions options, User user = null, BaseItem owner = null)
{ {
var dto = GetBaseItemDtoInternal(item, options, user, owner); var dto = GetBaseItemDtoInternal(item, options, user, owner);
var tvChannel = item as LiveTvChannel; if (item is LiveTvChannel tvChannel)
if (tvChannel != null)
{ {
var list = new List<Tuple<BaseItemDto, LiveTvChannel>> { new Tuple<BaseItemDto, LiveTvChannel>(dto, tvChannel) }; var list = new List<(BaseItemDto, LiveTvChannel)>(1) { (dto, tvChannel) };
_livetvManager().AddChannelInfo(list, options, user); _livetvManager().AddChannelInfo(list, options, user);
} }
else if (item is LiveTvProgram) else if (item is LiveTvProgram)
{ {
var list = new List<Tuple<BaseItem, BaseItemDto>> { new Tuple<BaseItem, BaseItemDto>(item, dto) }; var list = new List<(BaseItem, BaseItemDto)>(1) { (item, dto) };
var task = _livetvManager().AddInfoToProgramDto(list, options.Fields, user); var task = _livetvManager().AddInfoToProgramDto(list, options.Fields, user);
Task.WaitAll(task); Task.WaitAll(task);
} }
var byName = item as IItemByName; if (item is IItemByName itemByName
&& options.ContainsField(ItemFields.ItemCounts))
if (byName != null)
{ {
if (options.ContainsField(ItemFields.ItemCounts)) SetItemByNameInfo(
{ item,
SetItemByNameInfo(item, dto, GetTaggedItems(byName, user, new DtoOptions(false) dto,
{ GetTaggedItems(
EnableImages = false itemByName,
user,
}), user); new DtoOptions(false)
} {
EnableImages = false
return dto; }),
user);
} }
return dto; return dto;
@ -174,12 +170,12 @@ namespace Emby.Server.Implementations.Dto
private static IList<BaseItem> GetTaggedItems(IItemByName byName, User user, DtoOptions options) private static IList<BaseItem> GetTaggedItems(IItemByName byName, User user, DtoOptions options)
{ {
return byName.GetTaggedItems(new InternalItemsQuery(user) return byName.GetTaggedItems(
{ new InternalItemsQuery(user)
Recursive = true, {
DtoOptions = options Recursive = true,
DtoOptions = options
}); });
} }
private BaseItemDto GetBaseItemDtoInternal(BaseItem item, DtoOptions options, User user = null, BaseItem owner = null) private BaseItemDto GetBaseItemDtoInternal(BaseItem item, DtoOptions options, User user = null, BaseItem owner = null)
@ -222,8 +218,7 @@ namespace Emby.Server.Implementations.Dto
AttachUserSpecificInfo(dto, item, user, options); AttachUserSpecificInfo(dto, item, user, options);
} }
var hasMediaSources = item as IHasMediaSources; if (item is IHasMediaSources hasMediaSources)
if (hasMediaSources != null)
{ {
if (options.ContainsField(ItemFields.MediaSources)) if (options.ContainsField(ItemFields.MediaSources))
{ {
@ -769,14 +764,12 @@ namespace Emby.Server.Implementations.Dto
dto.CriticRating = item.CriticRating; dto.CriticRating = item.CriticRating;
var hasDisplayOrder = item as IHasDisplayOrder; if (item is IHasDisplayOrder hasDisplayOrder)
if (hasDisplayOrder != null)
{ {
dto.DisplayOrder = hasDisplayOrder.DisplayOrder; dto.DisplayOrder = hasDisplayOrder.DisplayOrder;
} }
var hasCollectionType = item as IHasCollectionType; if (item is IHasCollectionType hasCollectionType)
if (hasCollectionType != null)
{ {
dto.CollectionType = hasCollectionType.CollectionType; dto.CollectionType = hasCollectionType.CollectionType;
} }
@ -1073,17 +1066,24 @@ namespace Emby.Server.Implementations.Dto
if (options.ContainsField(ItemFields.LocalTrailerCount)) if (options.ContainsField(ItemFields.LocalTrailerCount))
{ {
int trailerCount = 0;
if (allExtras == null) if (allExtras == null)
{ {
allExtras = item.GetExtras().ToArray(); allExtras = item.GetExtras().ToArray();
} }
dto.LocalTrailerCount = allExtras.Count(i => i.ExtraType.HasValue && i.ExtraType.Value == ExtraType.Trailer) + item.GetTrailers().Count(); trailerCount += allExtras.Count(i => i.ExtraType.HasValue && i.ExtraType.Value == ExtraType.Trailer);
if (item is IHasTrailers hasTrailers)
{
trailerCount += hasTrailers.GetTrailerCount();
}
dto.LocalTrailerCount = trailerCount;
} }
// Add EpisodeInfo // Add EpisodeInfo
var episode = item as Episode; if (item is Episode episode)
if (episode != null)
{ {
dto.IndexNumberEnd = episode.IndexNumberEnd; dto.IndexNumberEnd = episode.IndexNumberEnd;
dto.SeriesName = episode.SeriesName; dto.SeriesName = episode.SeriesName;
@ -1101,7 +1101,7 @@ namespace Emby.Server.Implementations.Dto
Series episodeSeries = null; Series episodeSeries = null;
//if (options.ContainsField(ItemFields.SeriesPrimaryImage)) if (options.ContainsField(ItemFields.SeriesPrimaryImage))
{ {
episodeSeries = episodeSeries ?? episode.Series; episodeSeries = episodeSeries ?? episode.Series;
if (episodeSeries != null) if (episodeSeries != null)
@ -1121,8 +1121,7 @@ namespace Emby.Server.Implementations.Dto
} }
// Add SeriesInfo // Add SeriesInfo
var series = item as Series; if (item is Series series)
if (series != null)
{ {
dto.AirDays = series.AirDays; dto.AirDays = series.AirDays;
dto.AirTime = series.AirTime; dto.AirTime = series.AirTime;
@ -1130,8 +1129,7 @@ namespace Emby.Server.Implementations.Dto
} }
// Add SeasonInfo // Add SeasonInfo
var season = item as Season; if (item is Season season)
if (season != null)
{ {
dto.SeriesName = season.SeriesName; dto.SeriesName = season.SeriesName;
dto.SeriesId = season.SeriesId; dto.SeriesId = season.SeriesId;
@ -1147,7 +1145,7 @@ namespace Emby.Server.Implementations.Dto
} }
} }
//if (options.ContainsField(ItemFields.SeriesPrimaryImage)) if (options.ContainsField(ItemFields.SeriesPrimaryImage))
{ {
series = series ?? season.Series; series = series ?? season.Series;
if (series != null) if (series != null)
@ -1157,14 +1155,12 @@ namespace Emby.Server.Implementations.Dto
} }
} }
var musicVideo = item as MusicVideo; if (item is MusicVideo musicVideo)
if (musicVideo != null)
{ {
SetMusicVideoProperties(dto, musicVideo); SetMusicVideoProperties(dto, musicVideo);
} }
var book = item as Book; if (item is Book book)
if (book != null)
{ {
SetBookProperties(dto, book); SetBookProperties(dto, book);
} }
@ -1204,8 +1200,7 @@ namespace Emby.Server.Implementations.Dto
} }
} }
var photo = item as Photo; if (item is Photo photo)
if (photo != null)
{ {
SetPhotoProperties(dto, photo); SetPhotoProperties(dto, photo);
} }
@ -1224,8 +1219,7 @@ namespace Emby.Server.Implementations.Dto
private BaseItem GetImageDisplayParent(BaseItem currentItem, BaseItem originalItem) private BaseItem GetImageDisplayParent(BaseItem currentItem, BaseItem originalItem)
{ {
var musicAlbum = currentItem as MusicAlbum; if (currentItem is MusicAlbum musicAlbum)
if (musicAlbum != null)
{ {
var artist = musicAlbum.GetMusicArtist(new DtoOptions(false)); var artist = musicAlbum.GetMusicArtist(new DtoOptions(false));
if (artist != null) if (artist != null)

View file

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Security; using MediaBrowser.Controller.Security;
@ -89,7 +90,7 @@ namespace Emby.Server.Implementations.HttpServer.Security
AccessToken = token AccessToken = token
}); });
var tokenInfo = result.Items.Length > 0 ? result.Items[0] : null; var tokenInfo = result.Items.Count > 0 ? result.Items[0] : null;
if (tokenInfo != null) if (tokenInfo != null)
{ {
@ -190,17 +191,23 @@ namespace Emby.Server.Implementations.HttpServer.Security
/// <returns>Dictionary{System.StringSystem.String}.</returns> /// <returns>Dictionary{System.StringSystem.String}.</returns>
private Dictionary<string, string> GetAuthorization(string authorizationHeader) private Dictionary<string, string> GetAuthorization(string authorizationHeader)
{ {
if (authorizationHeader == null) return null; if (authorizationHeader == null)
{
return null;
}
var parts = authorizationHeader.Split(new[] { ' ' }, 2); var parts = authorizationHeader.Split(new[] { ' ' }, 2);
// There should be at least to parts // There should be at least to parts
if (parts.Length != 2) return null; if (parts.Length != 2)
{
return null;
}
var acceptedNames = new[] { "MediaBrowser", "Emby" }; var acceptedNames = new[] { "MediaBrowser", "Emby" };
// It has to be a digest request // It has to be a digest request
if (!acceptedNames.Contains(parts[0] ?? string.Empty, StringComparer.OrdinalIgnoreCase)) if (!acceptedNames.Contains(parts[0], StringComparer.OrdinalIgnoreCase))
{ {
return null; return null;
} }
@ -232,7 +239,7 @@ namespace Emby.Server.Implementations.HttpServer.Security
return value; return value;
} }
return System.Net.WebUtility.HtmlEncode(value); return WebUtility.HtmlEncode(value);
} }
} }
} }

View file

@ -1441,7 +1441,7 @@ namespace Emby.Server.Implementations.Library
return new QueryResult<BaseItem> return new QueryResult<BaseItem>
{ {
Items = list.ToArray() Items = list
}; };
} }
@ -1977,8 +1977,7 @@ namespace Emby.Server.Implementations.Library
public LibraryOptions GetLibraryOptions(BaseItem item) public LibraryOptions GetLibraryOptions(BaseItem item)
{ {
var collectionFolder = item as CollectionFolder; if (!(item is CollectionFolder collectionFolder))
if (collectionFolder == null)
{ {
collectionFolder = GetCollectionFolders(item) collectionFolder = GetCollectionFolders(item)
.OfType<CollectionFolder>() .OfType<CollectionFolder>()

View file

@ -224,7 +224,7 @@ namespace Emby.Server.Implementations.Library
return list; return list;
} }
private List<BaseItem> GetItemsForLatestItems(User user, LatestItemsQuery request, DtoOptions options) private IReadOnlyList<BaseItem> GetItemsForLatestItems(User user, LatestItemsQuery request, DtoOptions options)
{ {
var parentId = request.ParentId; var parentId = request.ParentId;
@ -236,24 +236,22 @@ namespace Emby.Server.Implementations.Library
if (!parentId.Equals(Guid.Empty)) if (!parentId.Equals(Guid.Empty))
{ {
var parentItem = _libraryManager.GetItemById(parentId); var parentItem = _libraryManager.GetItemById(parentId);
var parentItemChannel = parentItem as Channel; if (parentItem is Channel parentItemChannel)
if (parentItemChannel != null)
{ {
return _channelManager.GetLatestChannelItemsInternal(new InternalItemsQuery(user) return _channelManager.GetLatestChannelItemsInternal(
{ new InternalItemsQuery(user)
ChannelIds = new[] { parentId }, {
IsPlayed = request.IsPlayed, ChannelIds = new[] { parentId },
StartIndex = request.StartIndex, IsPlayed = request.IsPlayed,
Limit = request.Limit, StartIndex = request.StartIndex,
IncludeItemTypes = request.IncludeItemTypes, Limit = request.Limit,
EnableTotalRecordCount = false IncludeItemTypes = request.IncludeItemTypes,
EnableTotalRecordCount = false
},
}, CancellationToken.None).Result.Items.ToList(); CancellationToken.None).Result.Items;
} }
var parent = parentItem as Folder; if (parentItem is Folder parent)
if (parent != null)
{ {
parents.Add(parent); parents.Add(parent);
} }

View file

@ -881,7 +881,7 @@ namespace Emby.Server.Implementations.LiveTv
} }
var programList = _libraryManager.QueryItems(internalQuery).Items; var programList = _libraryManager.QueryItems(internalQuery).Items;
var totalCount = programList.Length; var totalCount = programList.Count;
var orderedPrograms = programList.Cast<LiveTvProgram>().OrderBy(i => i.StartDate.Date); var orderedPrograms = programList.Cast<LiveTvProgram>().OrderBy(i => i.StartDate.Date);
@ -969,8 +969,8 @@ namespace Emby.Server.Implementations.LiveTv
var timers = new Dictionary<string, List<TimerInfo>>(); var timers = new Dictionary<string, List<TimerInfo>>();
var seriesTimers = new Dictionary<string, List<SeriesTimerInfo>>(); var seriesTimers = new Dictionary<string, List<SeriesTimerInfo>>();
TimerInfo[] timerList = null; IReadOnlyList<TimerInfo> timerList = null;
SeriesTimerInfo[] seriesTimerList = null; IReadOnlyList<SeriesTimerInfo> seriesTimerList = null;
foreach (var programTuple in programs) foreach (var programTuple in programs)
{ {
@ -1296,6 +1296,7 @@ namespace Emby.Server.Implementations.LiveTv
} }
private const int MaxGuideDays = 14; private const int MaxGuideDays = 14;
private double GetGuideDays() private double GetGuideDays()
{ {
var config = GetConfiguration(); var config = GetConfiguration();
@ -1340,6 +1341,7 @@ namespace Emby.Server.Implementations.LiveTv
excludeItemTypes.Add(typeof(Movie).Name); excludeItemTypes.Add(typeof(Movie).Name);
} }
} }
if (query.IsSeries.HasValue) if (query.IsSeries.HasValue)
{ {
if (query.IsSeries.Value) if (query.IsSeries.Value)
@ -1351,10 +1353,12 @@ namespace Emby.Server.Implementations.LiveTv
excludeItemTypes.Add(typeof(Episode).Name); excludeItemTypes.Add(typeof(Episode).Name);
} }
} }
if (query.IsSports ?? false) if (query.IsSports ?? false)
{ {
genres.Add("Sports"); genres.Add("Sports");
} }
if (query.IsKids ?? false) if (query.IsKids ?? false)
{ {
genres.Add("Kids"); genres.Add("Kids");
@ -1400,20 +1404,20 @@ namespace Emby.Server.Implementations.LiveTv
if (query.IsInProgress ?? false) if (query.IsInProgress ?? false)
{ {
//TODO Fix The co-variant conversion between Video[] and BaseItem[], this can generate runtime issues. // TODO: Fix The co-variant conversion between Video[] and BaseItem[], this can generate runtime issues.
result.Items = result result.Items = result
.Items .Items
.OfType<Video>() .OfType<Video>()
.Where(i => !i.IsCompleteMedia) .Where(i => !i.IsCompleteMedia)
.ToArray(); .ToArray();
result.TotalRecordCount = result.Items.Length; result.TotalRecordCount = result.Items.Count;
} }
return result; return result;
} }
public Task AddInfoToProgramDto(List<Tuple<BaseItem, BaseItemDto>> tuples, ItemFields[] fields, User user = null) public Task AddInfoToProgramDto(IReadOnlyCollection<(BaseItem, BaseItemDto)> tuples, ItemFields[] fields, User user = null)
{ {
var programTuples = new List<Tuple<BaseItemDto, string, string>>(); var programTuples = new List<Tuple<BaseItemDto, string, string>>();
var hasChannelImage = fields.Contains(ItemFields.ChannelImage); var hasChannelImage = fields.Contains(ItemFields.ChannelImage);
@ -1877,7 +1881,7 @@ namespace Emby.Server.Implementations.LiveTv
return _libraryManager.GetItemById(internalChannelId); return _libraryManager.GetItemById(internalChannelId);
} }
public void AddChannelInfo(List<Tuple<BaseItemDto, LiveTvChannel>> tuples, DtoOptions options, User user) public void AddChannelInfo(IReadOnlyCollection<(BaseItemDto, LiveTvChannel)> tuples, DtoOptions options, User user)
{ {
var now = DateTime.UtcNow; var now = DateTime.UtcNow;

View file

@ -6,8 +6,8 @@ using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Emby.Server.Implementations.HttpServer; using Emby.Server.Implementations.HttpServer;
using Microsoft.AspNetCore.Http;
using MediaBrowser.Model.Services; using MediaBrowser.Model.Services;
using Microsoft.AspNetCore.Http;
namespace Emby.Server.Implementations.Services namespace Emby.Server.Implementations.Services
{ {

View file

@ -87,8 +87,7 @@ namespace Emby.Server.Implementations.Services
var response = actionContext.ServiceAction(instance, requestDto); var response = actionContext.ServiceAction(instance, requestDto);
var taskResponse = response as Task; if (response is Task taskResponse)
if (taskResponse != null)
{ {
return GetTaskResult(taskResponse); return GetTaskResult(taskResponse);
} }
@ -104,8 +103,7 @@ namespace Emby.Server.Implementations.Services
{ {
try try
{ {
var taskObject = task as Task<object>; if (task is Task<object> taskObject)
if (taskObject != null)
{ {
return await taskObject.ConfigureAwait(false); return await taskObject.ConfigureAwait(false);
} }
@ -136,7 +134,7 @@ namespace Emby.Server.Implementations.Services
} }
catch (TypeAccessException) catch (TypeAccessException)
{ {
return null; //return null for void Task's return null; // return null for void Task's
} }
} }
@ -155,29 +153,22 @@ namespace Emby.Server.Implementations.Services
Id = ServiceMethod.Key(serviceType, actionName, requestType.GetMethodName()) Id = ServiceMethod.Key(serviceType, actionName, requestType.GetMethodName())
}; };
try actionCtx.ServiceAction = CreateExecFn(serviceType, requestType, mi);
{
actionCtx.ServiceAction = CreateExecFn(serviceType, requestType, mi);
}
catch
{
//Potential problems with MONO, using reflection for fallback
actionCtx.ServiceAction = (service, request) =>
mi.Invoke(service, new[] { request });
}
var reqFilters = new List<IHasRequestFilter>(); var reqFilters = new List<IHasRequestFilter>();
foreach (var attr in mi.GetCustomAttributes(true)) foreach (var attr in mi.GetCustomAttributes(true))
{ {
var hasReqFilter = attr as IHasRequestFilter; if (attr is IHasRequestFilter hasReqFilter)
{
if (hasReqFilter != null)
reqFilters.Add(hasReqFilter); reqFilters.Add(hasReqFilter);
}
} }
if (reqFilters.Count > 0) if (reqFilters.Count > 0)
{
actionCtx.RequestFilters = reqFilters.OrderBy(i => i.Priority).ToArray(); actionCtx.RequestFilters = reqFilters.OrderBy(i => i.Priority).ToArray();
}
actions.Add(actionCtx); actions.Add(actionCtx);
} }
@ -198,15 +189,19 @@ namespace Emby.Server.Implementations.Services
if (mi.ReturnType != typeof(void)) if (mi.ReturnType != typeof(void))
{ {
var executeFunc = Expression.Lambda<ActionInvokerFn> var executeFunc = Expression.Lambda<ActionInvokerFn>(
(callExecute, serviceParam, requestDtoParam).Compile(); callExecute,
serviceParam,
requestDtoParam).Compile();
return executeFunc; return executeFunc;
} }
else else
{ {
var executeFunc = Expression.Lambda<VoidActionInvokerFn> var executeFunc = Expression.Lambda<VoidActionInvokerFn>(
(callExecute, serviceParam, requestDtoParam).Compile(); callExecute,
serviceParam,
requestDtoParam).Compile();
return (service, request) => return (service, request) =>
{ {

View file

@ -12,10 +12,10 @@ namespace Emby.Server.Implementations.Services
{ {
public static string GetMethodName(this Type type) public static string GetMethodName(this Type type)
{ {
var typeName = type.FullName != null //can be null, e.g. generic types var typeName = type.FullName != null // can be null, e.g. generic types
? LeftPart(type.FullName, "[[") //Generic Fullname ? LeftPart(type.FullName, "[[") // Generic Fullname
.Replace(type.Namespace + ".", "") //Trim Namespaces .Replace(type.Namespace + ".", string.Empty) // Trim Namespaces
.Replace("+", ".") //Convert nested into normal type .Replace("+", ".") // Convert nested into normal type
: type.Name; : type.Name;
return type.IsGenericParameter ? "'" + typeName : typeName; return type.IsGenericParameter ? "'" + typeName : typeName;
@ -23,7 +23,11 @@ namespace Emby.Server.Implementations.Services
private static string LeftPart(string strVal, string needle) private static string LeftPart(string strVal, string needle)
{ {
if (strVal == null) return null; if (strVal == null)
{
return null;
}
var pos = strVal.IndexOf(needle, StringComparison.OrdinalIgnoreCase); var pos = strVal.IndexOf(needle, StringComparison.OrdinalIgnoreCase);
return pos == -1 return pos == -1
? strVal ? strVal

View file

@ -741,7 +741,7 @@ namespace MediaBrowser.Api.LiveTv
var result = new QueryResult<BaseItemDto> var result = new QueryResult<BaseItemDto>
{ {
Items = returnArray, Items = returnArray,
TotalRecordCount = returnArray.Length TotalRecordCount = returnArray.Count
}; };
return ToOptimizedResult(result); return ToOptimizedResult(result);

View file

@ -243,7 +243,7 @@ namespace MediaBrowser.Api.Movies
} }
} }
return categories.OrderBy(i => i.RecommendationType).ThenBy(i => Guid.NewGuid()); return categories.OrderBy(i => i.RecommendationType);
} }
private IEnumerable<RecommendationDto> GetWithDirector(User user, IEnumerable<string> names, int itemLimit, DtoOptions dtoOptions, RecommendationType type) private IEnumerable<RecommendationDto> GetWithDirector(User user, IEnumerable<string> names, int itemLimit, DtoOptions dtoOptions, RecommendationType type)

View file

@ -189,11 +189,9 @@ namespace MediaBrowser.Api
var dtos = _dtoService.GetBaseItemDtos(items.Select(i => i.Item2).ToList(), dtoOptions, user); var dtos = _dtoService.GetBaseItemDtos(items.Select(i => i.Item2).ToList(), dtoOptions, user);
var index = 0; for (int index = 0; index < dtos.Count; index++)
foreach (var item in dtos)
{ {
item.PlaylistItemId = items[index].Item1.Id; dtos[index].PlaylistItemId = items[index].Item1.Id;
index++;
} }
var result = new QueryResult<BaseItemDto> var result = new QueryResult<BaseItemDto>

View file

@ -61,11 +61,6 @@ namespace MediaBrowser.Api
var dtoList = _dtoService.GetBaseItemDtos(result.Items, dtoOptions, user); var dtoList = _dtoService.GetBaseItemDtos(result.Items, dtoOptions, user);
if (dtoList == null)
{
throw new InvalidOperationException("GetBaseItemDtos returned null");
}
return new QueryResult<BaseItemDto> return new QueryResult<BaseItemDto>
{ {
TotalRecordCount = result.TotalRecordCount, TotalRecordCount = result.TotalRecordCount,

View file

@ -382,13 +382,13 @@ namespace MediaBrowser.Api
throw new ResourceNotFoundException("Series not found"); throw new ResourceNotFoundException("Series not found");
} }
var seasons = (series.GetItemList(new InternalItemsQuery(user) var seasons = series.GetItemList(new InternalItemsQuery(user)
{ {
IsMissing = request.IsMissing, IsMissing = request.IsMissing,
IsSpecialSeason = request.IsSpecialSeason, IsSpecialSeason = request.IsSpecialSeason,
AdjacentTo = request.AdjacentTo AdjacentTo = request.AdjacentTo
})); });
var dtoOptions = GetDtoOptions(_authContext, request); var dtoOptions = GetDtoOptions(_authContext, request);
@ -396,7 +396,7 @@ namespace MediaBrowser.Api
return new QueryResult<BaseItemDto> return new QueryResult<BaseItemDto>
{ {
TotalRecordCount = returnItems.Length, TotalRecordCount = returnItems.Count,
Items = returnItems Items = returnItems
}; };
} }

View file

@ -175,11 +175,6 @@ namespace MediaBrowser.Api.UserLibrary
var dtoList = _dtoService.GetBaseItemDtos(result.Items, dtoOptions, user); var dtoList = _dtoService.GetBaseItemDtos(result.Items, dtoOptions, user);
if (dtoList == null)
{
throw new InvalidOperationException("GetBaseItemDtos returned null");
}
return new QueryResult<BaseItemDto> return new QueryResult<BaseItemDto>
{ {
TotalRecordCount = result.TotalRecordCount, TotalRecordCount = result.TotalRecordCount,

View file

@ -2,6 +2,7 @@ using System;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Entities.Audio;
@ -367,12 +368,20 @@ namespace MediaBrowser.Api.UserLibrary
var dtoOptions = GetDtoOptions(_authContext, request); var dtoOptions = GetDtoOptions(_authContext, request);
var dtosExtras = item.GetExtras(new[] { ExtraType.Trailer }) var dtosExtras = item.GetExtras(new[] { ExtraType.Trailer })
.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, item)); .Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, item))
.ToArray();
var dtosTrailers = item.GetTrailers() if (item is IHasTrailers hasTrailers)
.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, item)); {
var trailers = hasTrailers.GetTrailers();
var dtosTrailers = _dtoService.GetBaseItemDtos(trailers, dtoOptions, user, item);
var allTrailers = new BaseItemDto[dtosExtras.Length + dtosTrailers.Count];
dtosExtras.CopyTo(allTrailers, 0);
dtosTrailers.CopyTo(allTrailers, dtosExtras.Length);
return ToOptimizedResult(allTrailers);
}
return ToOptimizedResult(dtosExtras.Concat(dtosTrailers).ToArray()); return ToOptimizedResult(dtosExtras);
} }
/// <summary> /// <summary>

View file

@ -248,9 +248,14 @@ namespace MediaBrowser.Api
private readonly INetworkManager _networkManager; private readonly INetworkManager _networkManager;
private readonly IDeviceManager _deviceManager; private readonly IDeviceManager _deviceManager;
private readonly IAuthorizationContext _authContext; private readonly IAuthorizationContext _authContext;
private readonly ILogger _logger;
public UserService(IUserManager userManager, ISessionManager sessionMananger, IServerConfigurationManager config, INetworkManager networkManager, IDeviceManager deviceManager, IAuthorizationContext authContext, ILoggerFactory loggerFactory) public UserService(
IUserManager userManager,
ISessionManager sessionMananger,
IServerConfigurationManager config,
INetworkManager networkManager,
IDeviceManager deviceManager,
IAuthorizationContext authContext)
{ {
_userManager = userManager; _userManager = userManager;
_sessionMananger = sessionMananger; _sessionMananger = sessionMananger;
@ -258,7 +263,6 @@ namespace MediaBrowser.Api
_networkManager = networkManager; _networkManager = networkManager;
_deviceManager = deviceManager; _deviceManager = deviceManager;
_authContext = authContext; _authContext = authContext;
_logger = loggerFactory.CreateLogger(nameof(UserService));
} }
public object Get(GetPublicUsers request) public object Get(GetPublicUsers request)

View file

@ -10,5 +10,22 @@ namespace MediaBrowser.Common.Extensions
dictionary.TryGetValue(key, out var ret); dictionary.TryGetValue(key, out var ret);
return ret; return ret;
} }
// REVIEW: Inline?
/// <summary>
/// Copies all the elements of the current collection to the specified list
/// starting at the specified destination array index. The index is specified as a 32-bit integer.
/// </summary>
/// <param name="source">The current collection that is the source of the elements.</param>
/// <param name="destination">The list that is the destination of the elements copied from the current collection.</param>
/// <param name="index">A 32-bit integer that represents the index in <c>destination</c> at which copying begins.</param>
/// <typeparam name="T"></typeparam>
public static void CopyTo<T>(this IReadOnlyCollection<T> source, IList<T> destination, int index = 0)
{
foreach (T item in source)
{
destination[index++] = item;
}
}
} }
} }

View file

@ -8,4 +8,4 @@ namespace MediaBrowser.Common.Net
public const string XForwardedProto = "X-Forwarded-Proto"; public const string XForwardedProto = "X-Forwarded-Proto";
public const string XRealIP = "X-Real-IP"; public const string XRealIP = "X-Real-IP";
} }
} }

View file

@ -57,7 +57,7 @@ namespace MediaBrowser.Controller.Dto
/// <param name="options">The options.</param> /// <param name="options">The options.</param>
/// <param name="user">The user.</param> /// <param name="user">The user.</param>
/// <param name="owner">The owner.</param> /// <param name="owner">The owner.</param>
BaseItemDto[] GetBaseItemDtos(IReadOnlyList<BaseItem> items, DtoOptions options, User user = null, BaseItem owner = null); IReadOnlyList<BaseItemDto> GetBaseItemDtos(IReadOnlyList<BaseItem> items, DtoOptions options, User user = null, BaseItem owner = null);
/// <summary> /// <summary>
/// Gets the item by name dto. /// Gets the item by name dto.

View file

@ -2871,16 +2871,16 @@ namespace MediaBrowser.Controller.Entities
/// Gets or sets the remote trailers. /// Gets or sets the remote trailers.
/// </summary> /// </summary>
/// <value>The remote trailers.</value> /// <value>The remote trailers.</value>
public MediaUrl[] RemoteTrailers { get; set; } public IReadOnlyList<MediaUrl> RemoteTrailers { get; set; }
public IEnumerable<BaseItem> GetExtras() public IEnumerable<BaseItem> GetExtras()
{ {
return ExtraIds.Select(LibraryManager.GetItemById).Where(i => i != null).OrderBy(i => i.SortName); return ExtraIds.Select(LibraryManager.GetItemById).Where(i => i != null).OrderBy(i => i.SortName);
} }
public IEnumerable<BaseItem> GetExtras(ExtraType[] extraTypes) public IEnumerable<BaseItem> GetExtras(IReadOnlyCollection<ExtraType> extraTypes)
{ {
return ExtraIds.Select(LibraryManager.GetItemById).Where(i => i != null && extraTypes.Contains(i.ExtraType.Value)).OrderBy(i => i.SortName); return ExtraIds.Select(LibraryManager.GetItemById).Where(i => i != null && extraTypes.Contains(i.ExtraType.Value));
} }
public IEnumerable<BaseItem> GetTrailers() public IEnumerable<BaseItem> GetTrailers()
@ -2908,7 +2908,7 @@ namespace MediaBrowser.Controller.Entities
} }
// Possible types of extra videos // Possible types of extra videos
public static ExtraType[] DisplayExtraTypes = new[] { Model.Entities.ExtraType.BehindTheScenes, Model.Entities.ExtraType.Clip, Model.Entities.ExtraType.DeletedScene, Model.Entities.ExtraType.Interview, Model.Entities.ExtraType.Sample, Model.Entities.ExtraType.Scene }; public static readonly IReadOnlyCollection<ExtraType> DisplayExtraTypes = new[] { Model.Entities.ExtraType.BehindTheScenes, Model.Entities.ExtraType.Clip, Model.Entities.ExtraType.DeletedScene, Model.Entities.ExtraType.Interview, Model.Entities.ExtraType.Sample, Model.Entities.ExtraType.Scene };
public virtual bool SupportsExternalTransfer => false; public virtual bool SupportsExternalTransfer => false;
} }

View file

@ -1,5 +1,6 @@
using System; using System;
using System.Linq; using System.Linq;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Model.Entities; using MediaBrowser.Model.Entities;
namespace MediaBrowser.Controller.Entities namespace MediaBrowser.Controller.Entities
@ -28,13 +29,17 @@ namespace MediaBrowser.Controller.Entities
Url = url Url = url
}; };
if (item.RemoteTrailers.Length == 0) if (item.RemoteTrailers.Count == 0)
{ {
item.RemoteTrailers = new[] { mediaUrl }; item.RemoteTrailers = new[] { mediaUrl };
} }
else else
{ {
item.RemoteTrailers = item.RemoteTrailers.Concat(new[] { mediaUrl }).ToArray(); var oldIds = item.RemoteTrailers;
var newIds = new MediaUrl[oldIds.Count + 1];
oldIds.CopyTo(newIds);
newIds[oldIds.Count] = mediaUrl;
item.RemoteTrailers = newIds;
} }
} }
} }

View file

@ -666,36 +666,36 @@ namespace MediaBrowser.Controller.Entities
query.StartIndex = null; query.StartIndex = null;
query.Limit = null; query.Limit = null;
var itemsList = LibraryManager.GetItemList(query); IEnumerable<BaseItem> itemsList = LibraryManager.GetItemList(query);
var user = query.User; var user = query.User;
if (user != null) if (user != null)
{ {
// needed for boxsets // needed for boxsets
itemsList = itemsList.Where(i => i.IsVisibleStandalone(query.User)).ToList(); itemsList = itemsList.Where(i => i.IsVisibleStandalone(query.User));
} }
BaseItem[] returnItems; IEnumerable<BaseItem> returnItems;
int totalCount = 0; int totalCount = 0;
if (query.EnableTotalRecordCount) if (query.EnableTotalRecordCount)
{ {
var itemsArray = itemsList.ToArray(); var itemArray = itemsList.ToArray();
totalCount = itemsArray.Length; totalCount = itemArray.Length;
returnItems = itemsArray; returnItems = itemArray;
} }
else else
{ {
returnItems = itemsList.ToArray(); returnItems = itemsList;
} }
if (limit.HasValue) if (limit.HasValue)
{ {
returnItems = returnItems.Skip(startIndex ?? 0).Take(limit.Value).ToArray(); returnItems = returnItems.Skip(startIndex ?? 0).Take(limit.Value);
} }
else if (startIndex.HasValue) else if (startIndex.HasValue)
{ {
returnItems = returnItems.Skip(startIndex.Value).ToArray(); returnItems = returnItems.Skip(startIndex.Value);
} }
return new QueryResult<BaseItem> return new QueryResult<BaseItem>

View file

@ -1,6 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using MediaBrowser.Model.Entities; using MediaBrowser.Model.Entities;
namespace MediaBrowser.Controller.Entities namespace MediaBrowser.Controller.Entities
@ -11,29 +10,82 @@ namespace MediaBrowser.Controller.Entities
/// Gets or sets the remote trailers. /// Gets or sets the remote trailers.
/// </summary> /// </summary>
/// <value>The remote trailers.</value> /// <value>The remote trailers.</value>
MediaUrl[] RemoteTrailers { get; set; } IReadOnlyList<MediaUrl> RemoteTrailers { get; set; }
/// <summary> /// <summary>
/// Gets or sets the local trailer ids. /// Gets or sets the local trailer ids.
/// </summary> /// </summary>
/// <value>The local trailer ids.</value> /// <value>The local trailer ids.</value>
Guid[] LocalTrailerIds { get; set; } IReadOnlyList<Guid> LocalTrailerIds { get; set; }
Guid[] RemoteTrailerIds { get; set; }
/// <summary>
/// Gets or sets the remote trailer ids.
/// </summary>
/// <value>The remote trailer ids.</value>
IReadOnlyList<Guid> RemoteTrailerIds { get; set; }
Guid Id { get; set; } Guid Id { get; set; }
} }
/// <summary>
/// Class providing extension methods for working with <see cref="IHasTrailers" />.
/// </summary>
public static class HasTrailerExtensions public static class HasTrailerExtensions
{ {
/// <summary>
/// Gets the trailer count.
/// </summary>
/// <returns><see cref="IReadOnlyList{Guid}" />.</returns>
public static int GetTrailerCount(this IHasTrailers item)
=> item.LocalTrailerIds.Count + item.RemoteTrailerIds.Count;
/// <summary> /// <summary>
/// Gets the trailer ids. /// Gets the trailer ids.
/// </summary> /// </summary>
/// <returns>List&lt;Guid&gt;.</returns> /// <returns><see cref="IReadOnlyList{Guid}" />.</returns>
public static List<Guid> GetTrailerIds(this IHasTrailers item) public static IReadOnlyList<Guid> GetTrailerIds(this IHasTrailers item)
{ {
var list = item.LocalTrailerIds.ToList(); var localIds = item.LocalTrailerIds;
list.AddRange(item.RemoteTrailerIds); var remoteIds = item.RemoteTrailerIds;
return list;
var all = new Guid[localIds.Count + remoteIds.Count];
var index = 0;
foreach (var id in localIds)
{
all[index++] = id;
}
foreach (var id in remoteIds)
{
all[index++] = id;
}
return all;
} }
/// <summary>
/// Gets the trailers.
/// </summary>
/// <returns><see cref="IReadOnlyList{BaseItem}" />.</returns>
public static IReadOnlyList<BaseItem> GetTrailers(this IHasTrailers item)
{
var localIds = item.LocalTrailerIds;
var remoteIds = item.RemoteTrailerIds;
var libraryManager = BaseItem.LibraryManager;
var all = new BaseItem[localIds.Count + remoteIds.Count];
var index = 0;
foreach (var id in localIds)
{
all[index++] = libraryManager.GetItemById(id);
}
foreach (var id in remoteIds)
{
all[index++] = libraryManager.GetItemById(id);
}
return all;
}
} }
} }

View file

@ -33,8 +33,11 @@ namespace MediaBrowser.Controller.Entities.Movies
[IgnoreDataMember] [IgnoreDataMember]
public override bool SupportsPeople => true; public override bool SupportsPeople => true;
public Guid[] LocalTrailerIds { get; set; } /// <inheritdoc />
public Guid[] RemoteTrailerIds { get; set; } public IReadOnlyList<Guid> LocalTrailerIds { get; set; }
/// <inheritdoc />
public IReadOnlyList<Guid> RemoteTrailerIds { get; set; }
/// <summary> /// <summary>
/// Gets or sets the display order. /// Gets or sets the display order.
@ -61,7 +64,8 @@ namespace MediaBrowser.Controller.Entities.Movies
{ {
return base.GetNonCachedChildren(directoryService); return base.GetNonCachedChildren(directoryService);
} }
return new List<BaseItem>();
return Enumerable.Empty<BaseItem>();
} }
protected override List<BaseItem> LoadChildren() protected override List<BaseItem> LoadChildren()

View file

@ -27,8 +27,11 @@ namespace MediaBrowser.Controller.Entities.Movies
RemoteTrailerIds = Array.Empty<Guid>(); RemoteTrailerIds = Array.Empty<Guid>();
} }
public Guid[] LocalTrailerIds { get; set; } /// <inheritdoc />
public Guid[] RemoteTrailerIds { get; set; } public IReadOnlyList<Guid> LocalTrailerIds { get; set; }
/// <inheritdoc />
public IReadOnlyList<Guid> RemoteTrailerIds { get; set; }
/// <summary> /// <summary>
/// Gets or sets the name of the TMDB collection. /// Gets or sets the name of the TMDB collection.

View file

@ -23,8 +23,11 @@ namespace MediaBrowser.Controller.Entities.TV
RemoteTrailerIds = Array.Empty<Guid>(); RemoteTrailerIds = Array.Empty<Guid>();
} }
public Guid[] LocalTrailerIds { get; set; } /// <inheritdoc />
public Guid[] RemoteTrailerIds { get; set; } public IReadOnlyList<Guid> LocalTrailerIds { get; set; }
/// <inheritdoc />
public IReadOnlyList<Guid> RemoteTrailerIds { get; set; }
/// <summary> /// <summary>
/// Gets the season in which it aired. /// Gets the season in which it aired.

View file

@ -46,8 +46,11 @@ namespace MediaBrowser.Controller.Entities.TV
[IgnoreDataMember] [IgnoreDataMember]
public override bool SupportsPeople => true; public override bool SupportsPeople => true;
public Guid[] LocalTrailerIds { get; set; } /// <inheritdoc />
public Guid[] RemoteTrailerIds { get; set; } public IReadOnlyList<Guid> LocalTrailerIds { get; set; }
/// <inheritdoc />
public IReadOnlyList<Guid> RemoteTrailerIds { get; set; }
/// <summary> /// <summary>
/// airdate, dvd or absolute /// airdate, dvd or absolute

View file

@ -221,7 +221,7 @@ namespace MediaBrowser.Controller.LiveTv
/// <param name="fields">The fields.</param> /// <param name="fields">The fields.</param>
/// <param name="user">The user.</param> /// <param name="user">The user.</param>
/// <returns>Task.</returns> /// <returns>Task.</returns>
Task AddInfoToProgramDto(List<Tuple<BaseItem, BaseItemDto>> programs, ItemFields[] fields, User user = null); Task AddInfoToProgramDto(IReadOnlyCollection<(BaseItem, BaseItemDto)> programs, ItemFields[] fields, User user = null);
/// <summary> /// <summary>
/// Saves the tuner host. /// Saves the tuner host.
@ -258,7 +258,7 @@ namespace MediaBrowser.Controller.LiveTv
/// <param name="items">The items.</param> /// <param name="items">The items.</param>
/// <param name="options">The options.</param> /// <param name="options">The options.</param>
/// <param name="user">The user.</param> /// <param name="user">The user.</param>
void AddChannelInfo(List<Tuple<BaseItemDto, LiveTvChannel>> items, DtoOptions options, User user); void AddChannelInfo(IReadOnlyCollection<(BaseItemDto, LiveTvChannel)> items, DtoOptions options, User user);
Task<List<ChannelInfo>> GetChannelsForListingsProvider(string id, CancellationToken cancellationToken); Task<List<ChannelInfo>> GetChannelsForListingsProvider(string id, CancellationToken cancellationToken);
Task<List<ChannelInfo>> GetChannelsFromListingsProviderData(string id, CancellationToken cancellationToken); Task<List<ChannelInfo>> GetChannelsFromListingsProviderData(string id, CancellationToken cancellationToken);

View file

@ -228,7 +228,7 @@ namespace MediaBrowser.LocalMetadata.Savers
} }
} }
if (item.RemoteTrailers.Length > 0) if (item.RemoteTrailers.Count > 0)
{ {
writer.WriteStartElement("Trailers"); writer.WriteStartElement("Trailers");

View file

@ -234,7 +234,7 @@ namespace MediaBrowser.Model.Dto
/// Gets or sets the trailer urls. /// Gets or sets the trailer urls.
/// </summary> /// </summary>
/// <value>The trailer urls.</value> /// <value>The trailer urls.</value>
public MediaUrl[] RemoteTrailers { get; set; } public IReadOnlyCollection<MediaUrl> RemoteTrailers { get; set; }
/// <summary> /// <summary>
/// Gets or sets the provider ids. /// Gets or sets the provider ids.

View file

@ -1,10 +1,11 @@
using System; using System;
using System.Collections.Generic;
namespace MediaBrowser.Model.Dto namespace MediaBrowser.Model.Dto
{ {
public class RecommendationDto public class RecommendationDto
{ {
public BaseItemDto[] Items { get; set; } public IReadOnlyCollection<BaseItemDto> Items { get; set; }
public RecommendationType RecommendationType { get; set; } public RecommendationType RecommendationType { get; set; }

View file

@ -1,3 +1,6 @@
using System;
using System.Collections.Generic;
namespace MediaBrowser.Model.Querying namespace MediaBrowser.Model.Querying
{ {
public class QueryResult<T> public class QueryResult<T>
@ -6,7 +9,7 @@ namespace MediaBrowser.Model.Querying
/// Gets or sets the items. /// Gets or sets the items.
/// </summary> /// </summary>
/// <value>The items.</value> /// <value>The items.</value>
public T[] Items { get; set; } public IReadOnlyList<T> Items { get; set; }
/// <summary> /// <summary>
/// The total number of records available /// The total number of records available
@ -16,7 +19,7 @@ namespace MediaBrowser.Model.Querying
public QueryResult() public QueryResult()
{ {
Items = new T[] { }; Items = Array.Empty<T>();
} }
} }
} }

View file

@ -11,7 +11,8 @@ namespace MediaBrowser.Providers.Manager
{ {
public static class ProviderUtils public static class ProviderUtils
{ {
public static void MergeBaseItemData<T>(MetadataResult<T> sourceResult, public static void MergeBaseItemData<T>(
MetadataResult<T> sourceResult,
MetadataResult<T> targetResult, MetadataResult<T> targetResult,
MetadataFields[] lockedFields, MetadataFields[] lockedFields,
bool replaceData, bool replaceData,
@ -174,11 +175,11 @@ namespace MediaBrowser.Providers.Manager
} }
} }
MergeAlbumArtist(source, target, lockedFields, replaceData); MergeAlbumArtist(source, target, replaceData);
MergeCriticRating(source, target, lockedFields, replaceData); MergeCriticRating(source, target, replaceData);
MergeTrailers(source, target, lockedFields, replaceData); MergeTrailers(source, target, replaceData);
MergeVideoInfo(source, target, lockedFields, replaceData); MergeVideoInfo(source, target, replaceData);
MergeDisplayOrder(source, target, lockedFields, replaceData); MergeDisplayOrder(source, target, replaceData);
if (replaceData || string.IsNullOrEmpty(target.ForcedSortName)) if (replaceData || string.IsNullOrEmpty(target.ForcedSortName))
{ {
@ -196,7 +197,7 @@ namespace MediaBrowser.Providers.Manager
target.IsLocked = source.IsLocked; target.IsLocked = source.IsLocked;
// Grab the value if it's there, but if not then don't overwrite the default // Grab the value if it's there, but if not then don't overwrite the default
if (source.DateCreated != default(DateTime)) if (source.DateCreated != default)
{ {
target.DateCreated = source.DateCreated; target.DateCreated = source.DateCreated;
} }
@ -231,12 +232,10 @@ namespace MediaBrowser.Providers.Manager
} }
} }
private static void MergeDisplayOrder(BaseItem source, BaseItem target, MetadataFields[] lockedFields, bool replaceData) private static void MergeDisplayOrder(BaseItem source, BaseItem target, bool replaceData)
{ {
var sourceHasDisplayOrder = source as IHasDisplayOrder; if (source is IHasDisplayOrder sourceHasDisplayOrder
var targetHasDisplayOrder = target as IHasDisplayOrder; && target is IHasDisplayOrder targetHasDisplayOrder)
if (sourceHasDisplayOrder != null && targetHasDisplayOrder != null)
{ {
if (replaceData || string.IsNullOrEmpty(targetHasDisplayOrder.DisplayOrder)) if (replaceData || string.IsNullOrEmpty(targetHasDisplayOrder.DisplayOrder))
{ {
@ -250,7 +249,7 @@ namespace MediaBrowser.Providers.Manager
} }
} }
private static void MergeAlbumArtist(BaseItem source, BaseItem target, MetadataFields[] lockedFields, bool replaceData) private static void MergeAlbumArtist(BaseItem source, BaseItem target, bool replaceData)
{ {
if (source is IHasAlbumArtist sourceHasAlbumArtist if (source is IHasAlbumArtist sourceHasAlbumArtist
&& target is IHasAlbumArtist targetHasAlbumArtist) && target is IHasAlbumArtist targetHasAlbumArtist)
@ -262,7 +261,7 @@ namespace MediaBrowser.Providers.Manager
} }
} }
private static void MergeCriticRating(BaseItem source, BaseItem target, MetadataFields[] lockedFields, bool replaceData) private static void MergeCriticRating(BaseItem source, BaseItem target, bool replaceData)
{ {
if (replaceData || !target.CriticRating.HasValue) if (replaceData || !target.CriticRating.HasValue)
{ {
@ -270,20 +269,17 @@ namespace MediaBrowser.Providers.Manager
} }
} }
private static void MergeTrailers(BaseItem source, BaseItem target, MetadataFields[] lockedFields, bool replaceData) private static void MergeTrailers(BaseItem source, BaseItem target, bool replaceData)
{ {
if (replaceData || target.RemoteTrailers.Length == 0) if (replaceData || target.RemoteTrailers.Count == 0)
{ {
target.RemoteTrailers = source.RemoteTrailers; target.RemoteTrailers = source.RemoteTrailers;
} }
} }
private static void MergeVideoInfo(BaseItem source, BaseItem target, MetadataFields[] lockedFields, bool replaceData) private static void MergeVideoInfo(BaseItem source, BaseItem target, bool replaceData)
{ {
var sourceCast = source as Video; if (source is Video sourceCast && target is Video targetCast)
var targetCast = target as Video;
if (sourceCast != null && targetCast != null)
{ {
if (replaceData || targetCast.Video3DFormat == null) if (replaceData || targetCast.Video3DFormat == null)
{ {

View file

@ -28,5 +28,5 @@
<!-- We need at least C# 7.1 --> <!-- We need at least C# 7.1 -->
<LangVersion>latest</LangVersion> <LangVersion>latest</LangVersion>
</PropertyGroup> </PropertyGroup>
</Project> </Project>