Я пытаюсь реализовать карту идентификации с использованием обобщений. У меня есть абстрактный класс Entity и ограничение деривации на карте для Entity. Поскольку моя карта должна иметь возможность создавать экземпляры сущностей, моя карта также имеет ограничение конструктора.
Однако, чтобы карта была полезной, подклассы Entity не должны иметь возможности создания экземпляров из клиентского кода, а это значит, что мне нужен внутренний конструктор, а не публичные конструкторы. Это противоречит ограничению конструктора.
Есть ли что-то, что я пропускаю? Есть ли способ рефакторинга, чтобы получить желаемый результат?
Следующий код компилируется как есть, но в идеале конструкторы подклассов Entity должны быть внутренними:
public abstract class Entity
{
public int Id { get; protected internal set; }
}
public sealed class Widget : Entity
{
// Client code should not be allowed to instantiate entities.
// But the constraints on EntityMap require that entities have
// a public constructor.
public Widget() { }
}
public sealed class Gadget : Entity
{
public Gadget() { }
}
// The new() constraint is required so that Get() can instantiate Ts.
public class EntityMap<T> where T : Entity, new()
{
private Dictionary<int, T> _entities = new Dictionary<int, T>();
private object _getLock = new object();
public T Get(int id)
{
lock (_getLock)
{
if (!_entities.ContainsKey(id))
_entities.Add(id, new T() { Id = id });
}
return _entities[id];
}
// Client code should not be allowed to instantiate maps.
internal EntityMap() { }
}
// Ideally, the client would only be able to obtain Entity
// references through EntityMaps, which are only accessible
// through the ApplicationMap.
public static class ApplicationMap
{
public static EntityMap<Widget> Widgets = new EntityMap<Widget>();
public static EntityMap<Gadget> Gadgets = new EntityMap<Gadget>();
}