Вызовите функцию класса generi c извне - PullRequest
1 голос
/ 07 апреля 2020

Я создаю интерфейс для сторонней базы данных. Я столкнулся с проблемой класса c в C#. Я не могу получить работу класса Generi c в этом случае.

У меня есть такой код:

class Program
{
    static void Main(string[] args)
    {
        Collection collection= new Collection();
        collection.Save();
    }
}

public class Collection : CollectionBase
{
    public DataTable<ItemA> itemA = new DataTable<ItemA>();
    public DataTable<ItemB> itemB = new DataTable<ItemB>();
}

public class CollectionBase
{ 
    public void Save()
    {
        var MyFields = this.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);

        foreach (var Field in MyFields)
        {
            if (Field.FieldType.IsGenericType && Field.FieldType.GetGenericTypeDefinition() == typeof(DataTable<>))
            {
                var ItemInstance = Field.GetValue(this);
                //ItemInstance.SaveAll(); //<--This is Missing
                var Item = ItemInstance as DataTable<BaseItem>; //<-- Returns null, debuger says this is DataTable<ItemA> (or ItemB at second loop)
                Item.SaveAll(); //<--(And fails for null exception, of cource)
            }
        }

    }
}

public class DataTable<T>
{
    public IQueryable<T> Where(Expression<Func<T, bool>> condition)
    {
        //...
        return null;
    }
    public void SaveAll() { }
}

public class BaseItem
{}
public class ItemA : BaseItem
{}
public class ItemB : BaseItem 
{}

Field.GetValue (this) возвращает правильный экземпляр, но я могу ' Найти способ вызова функции SaveAll объекта DataTable <>.

Возможно ли это?

Я знаю, что могу обойти эту проблему, создав собственную функцию Save (в данном случае) для класса Collection, но я не хочу, чтобы этот код был таким.

1 Ответ

2 голосов
/ 07 апреля 2020

Ваш класс DataTable<T> не является ковариантным, поэтому вы не можете присвоить объект типа DataTable<Derived> переменной DataTable<Base>.

Фактически, NET не поддерживает generi c дисперсия типа в классах вообще.

Что вы можете сделать, это создать ковариантный интерфейс, используя ключевое слово out:

IDataTable<out T>
{
    void SaveAll();
}

Затем получите DataTable<T> реализовать это:

public class DataTable<T> : IDataTable<T>

Тогда вы можете сделать это:

var item = ItemInstance as IDataTable<BaseItem>;
item.SaveAll();

Дополнительная информация: Ковариантность и Контравариантность в обобщениях .

...