using System;
using System.Collections.Generic;
using System.Linq;
namespace Umbraco.Core.Composing
{
///
/// Implements a weighted collection builder.
///
/// The type of the builder.
/// The type of the collection.
/// The type of the items.
public abstract class WeightedCollectionBuilderBase : CollectionBuilderBase
where TBuilder : WeightedCollectionBuilderBase
where TCollection : class, IBuilderCollection
{
protected abstract TBuilder This { get; }
///
/// Clears all types in the collection.
///
/// The builder.
public TBuilder Clear()
{
Configure(types => types.Clear());
return This;
}
///
/// Adds a type to the collection.
///
/// The type to add.
/// The builder.
public TBuilder Add()
where T : TItem
{
Configure(types =>
{
var type = typeof(T);
if (types.Contains(type) == false) types.Add(type);
});
return This;
}
///
/// Adds a type to the collection.
///
/// The type to add.
/// The builder.
public TBuilder Add(Type type)
{
Configure(types =>
{
EnsureType(type, "register");
if (types.Contains(type) == false) types.Add(type);
});
return This;
}
///
/// Adds types to the collection.
///
/// The types to add.
/// The builder.
public TBuilder Add(IEnumerable types)
{
Configure(list =>
{
foreach (var type in types)
{
// would be detected by CollectionBuilderBase when registering, anyways, but let's fail fast
EnsureType(type, "register");
if (list.Contains(type) == false) list.Add(type);
}
});
return This;
}
///
/// Removes a type from the collection.
///
/// The type to remove.
/// The builder.
public TBuilder Remove()
where T : TItem
{
Configure(types =>
{
var type = typeof(T);
if (types.Contains(type)) types.Remove(type);
});
return This;
}
///
/// Removes a type from the collection.
///
/// The type to remove.
/// The builder.
public TBuilder Remove(Type type)
{
Configure(types =>
{
EnsureType(type, "remove");
if (types.Contains(type)) types.Remove(type);
});
return This;
}
protected override IEnumerable GetRegisteringTypes(IEnumerable types)
{
var list = types.ToList();
list.Sort((t1, t2) => GetWeight(t1).CompareTo(GetWeight(t2)));
return list;
}
public virtual int DefaultWeight { get; set; } = 100;
protected virtual int GetWeight(Type type)
{
var attr = type.GetCustomAttributes(typeof(WeightAttribute), false).OfType().SingleOrDefault();
return attr?.Weight ?? DefaultWeight;
}
}
}