#c# #generics #covariance #self-reference
#c# #обобщения #ковариация #самоссылка
Вопрос:
У меня есть кое-что, связывающее это:
public abstract class Wrapper<T, TWrapped>: where TWrapped : Wrapper<T, TWrapped>
{
protected T baseObject;
protected ICollection<T> baseList;
protected ICollection<TWrapped> wrappedList;
public Wrapper (T base, ICollection<T> baseList, ICollection<TWrapped> wrappedList) { }
}
Затем, когда я получаю из него, мне нужно что-то вроде:
public class Base { }
public class Sample: Wrapper<Base, Sample> { }
Есть ли способ удалить TWrapped
и создать ссылку на производный тип? Я пытался использовать ICollection<Wrapped<T>>
, но потом я вспоминаю, что в ICollection
нет ковариации.
РЕДАКТИРОВАТЬ: Пояснения, что я хочу с помощью этой оболочки, так это обеспечить функциональность удаления (и некоторые другие вещи) внутри объекта (я не могу изменить базовый объект, поэтому мне нужна оболочка, чтобы придать эту функциональность и манипулировать ею). Этот абстрактный класс будет иметь методы, подобные этому:
void Remove()
{
while(this.baseList.Remove(baseObject));
this.baseList = null;
while(this.wrappedList.Remove((TWrapped)this));
this.wrappedList = null;
}
Комментарии:
1. Извините, я упускаю суть. Возможно, вам следует объяснить, почему вы пришли к этому … хитроумному решению и, возможно, как вы обычно его используете. У меня отчетливое ощущение, что здесь есть по крайней мере один ненужный уровень сложности (и в противном случае слои должны быть разделены для ясности)
2. Чего пытается достичь класс? т.Е. как вы собираетесь это использовать?
3. Я уже решил свою проблему. Я изменил способ приближения к нему. Я опубликую ответ с решением позже (я новый пользователь, я не могу опубликовать ответ для себя раньше, чем через 8 часов).
Ответ №1:
В конечном итоге я меняю логику того, как я собираюсь синхронизировать списки и разрешить элементам удалять себя. Я создал новый класс для хранения коллекции обернутых элементов:
public interface IWrapper<TModel>
{
TModel Model { get; }
}
public class WrapperCollection<TWrapper, TModel> : ObservableCollection<TWrapper> where TWrapper : IWrapper<TModel>
{
protected IList<TModel> modelList;
public ReadOnlyObservableCollection<TWrapper> AsReadOnly { get; private set; }
protected WrapperCollection(IList<TModel> modelList)
{
this.modelList = modelList;
AsReadOnly = new ReadOnlyObservableCollection<TWrapper>(this);
}
public WrapperCollection(IList<TModel> modelList, Func<TModel, TWrapper> newWrapper)
:this(modelList)
{
foreach (TModel model in modelList)
this.Items.Add(newWrapper(model));
}
public WrapperCollection(IList<TModel> modelList, Func<TModel, WrapperCollection<TWrapper, TModel>, TWrapper> newWrapper)
: this(modelList)
{
foreach (TModel model in modelList)
this.Items.Add(newWrapper(model, this));
}
protected override void ClearItems()
{
modelList.Clear();
base.ClearItems();
}
protected override void InsertItem(int index, TWrapper item)
{
modelList.Insert(index, item.Model);
base.InsertItem(index, item);
}
protected override void RemoveItem(int index)
{
modelList.RemoveAt(index);
base.RemoveItem(index);
}
protected override void SetItem(int index, TWrapper item)
{
modelList[index] = item.Model;
base.SetItem(index, item);
}
}
Использование примера класса:
public class wrappedInt: IWrapper<int>
{
private WrapperCollection<wrappedInt, int> list;
public Model { get; private set; }
public wrappedInt(int source, WrapperCollection<wrappedInt, int> list)
{
this.Model = source;
this.list = list;
}
public void RemoveMe()
{
if (list != null)
{
list.Remove(this);
list = null;
}
}
}
Тогда я могу создать экземпляр коллекции с помощью new WrapperCollection<wrappedInt, int>(listOfInts, (model, parent) => new wrappedInt(model, parent));
.