У меня есть связь m-to-n между исходными и целевыми форматами. (сейчас m = 2 и n = 5, причем n растет быстрее, чем m).Создавать различные типы данных с одинаковыми аргументами
Я хочу, чтобы получить событие, формат ввода Будучи Item
или DbDataReader
, и конвертировать его в другие виды, которые должны обеспечить необходимые конструкторы:
public MyEvent(Item item)
public MyEvent(DbDataReader ddr)
public MyEventDetailed(Item item)
public MyEventDetailed(DbDataReader ddr)
public MyEventInfo(Item item)
public MyEventInfo(DbDataReader ddr)
public MyEventNotification(Item item)
public MyEventNotification(DbDataReader ddr)
public MyEventReminder(Item item)
public MyEventReminder(DbDataReader ddr)
Каждые конструкторы должны быть использовано ровно один из двух DataStores:
EwsDataStore : DataStoreBase
DbDataStore : DataStoreBase
, который сейчас каждый реализовать абстрактный getEvent
метод из DataStoreBase
:
abstract MyEventDetailed getEvent(string uniqueId);
Теперь мне нужно все другие целевые форматы, а также, так что я хочу, чтобы сделать их родовыми так:
abstract T getEvent<T>(string uniqueId) where T : IEvent, new()
с возможным осуществлением EwsDataStore быть
getEvent<T>(string uniqueId) where T : IEvent, new() // TODO: All affected models have to implement IEvent interface
{
Item item;
try {
item = Item.Bind(service, new ItemId(uniqueId));
} catch(Exception e) {
throw new ArgumentException("An item by that Id was not found in the data store", "uniqueId", e);
}
// return T.FromItem(item); // Needs static IEvent.FromItem method.
return new T(item); // IEvent has to enforce constructor with parameter Item on all implementing classes
}
и для Sql:
getEvent<T>(string uniqueId) where T:IEvent, new() // TODO: All affected models have to implement IEvent interface
{
SQL db = new SQL();
db.AddParameter("@uniqueId", uniqueId)
SqlDataReader sdr = db.ExecuteReader("SELECT * FROM datastore WHERE uniqueId = @uniqueId");
if(!sdr.HasRows) throw new ArgumentException("An item by that Id was not found in the data store");
sdr.Read();
// return T.FromDdr(sdr); // Needs static IEvent.FromDdr method.
return new T(sdr); // IEvent has to enforce constructor with parameter DataReader on all implementing classes
}
Но ни конструктор с параметрами, ни статический Метод будет разрешен на универсальном типе, каждый бросает одну из следующих двух сообщений об ошибке:
Модификатор «статических» не является допустимым для этого элемента
«T»: не может предоставить аргументы при создании экземпляра переменный тип
Поиск этих сообщений об ошибках; Я обнаружил, что "the instance method can simply (sic!) delegate to a static method", или я могу использовать Reflection
или Activator
.
Ни один из них не кажется достаточно простым/понятным, чтобы писать, понимать, использовать и поддерживать.
Есть ли простой способ использования наследования и генерических средств для создания всех разных типов на основе типа I, который может быть понят/за ним следуют другие программисты, даже если они не владеют глубиной в наследовании C#?
Это означает, что отсутствующий конструктор вызывает ошибку времени выполнения, а не ошибку времени компиляции. Есть ли возможность сделать ошибку времени компиляции? – Alexander
@Alexander Нет, невозможно ограничить 'T', чтобы он имел доступный конструктор, независимо от того, что такое подпись. 'new' только устанавливает, что' new T() 'является действительным вызовом. – InBetween