получение ошибки при приведении объекта к system.Func

#c# #.net #generics #caching #.net-core

#c# #.net #общие #кэширование #.net-ядро

Вопрос:

У меня есть приведенный ниже код, в котором я перебираю материалы и создаю объект модели osm и добавляю его в список материалов ( material vector ) , и это работает нормально.

Здесь я добавляю создание повторяющихся объектов модели osm из-за повторяющихся материалов. поэтому, чтобы избежать этого, я реализую общий конкретный класс, который имеет обычный словарь для кэширования объектов и параметр Func factory для создания новых элементов, если они не найдены в кэше

     public Construction AddToOsm(Model model)
    {
        if (model is null)
        {
            throw new ArgumentNullException(nameof(model));
        }

        var construction = new Construction(model);
        construction.setName($"{this.Name} - {this.AshraeClimateZone?.Name}");

        using var materials = new MaterialVector();
        foreach (var glazingMaterial in this.Layers)
        {
            if (glazingMaterial != default)
            {
                using var material = glazingMaterial.AddToOsm(model); // here i am creating duplicate osm model objects 
                materials.Add(material);
            }
        }

        construction.setLayers(materials);
        return construction;
    }
  

и ниже приведен класс, в котором я реализую эту проверку для создания или извлечения объектов

 public class CacheObject<T>
{
    private readonly Dictionary<object, T> _cache = new Dictionary<object, T>();
    public T GetOrCreate(object key, Func<T> createItem)
    {
        if (!_cache.ContainsKey(key))
        {
            _cache[key] = createItem();
        }
        return _cache[key];
    }

}
  

и затем я использую вышеуказанный метод, как показано ниже

         using var materials = new MaterialVector();
        foreach (var glazingMaterial in this.Layers)
        {
            if (glazingMaterial != default)
            {
                var cacheObject = new CacheObject<FenestrationMaterial>();

                using var material = cacheObject.GetOrCreate(glazingMaterial.Id, glazingMaterial.AddToOsm(model)); // getting an object casting exception
               // using var material = glazingMaterial.AddToOsm(model);
                materials.Add(material);
            }
        }
  

Я получаю ошибку в этой строке

 using var material = cacheObject.GetOrCreate(glazingMaterial.Id, glazingMaterial.AddToOsm(model));
  

и ошибка

не удается преобразовать из ‘OpenStudio.Перенос материала «в» систему.Функция ‘

Не мог бы кто-нибудь, пожалуйста, предложить какие-либо идеи по этому поводу, как преодолеть эту ошибку или любое другое предложение, если я делаю неправильно, было бы очень благодарно мне.

заранее большое спасибо

Комментарии:

1. Вы имели в виду передать glazingMaterial.AddToOsm(model) как Func<T> createItem cacheObject.GetOrCreate() метод to? Происходит то, что вместо этого вы передаете результат этого вызова

Ответ №1:

Попробуйте это

 var material = cacheObject.GetOrCreate(glazingMaterial.Id, () => glazingMaterial.AddToOsm(model));
  

GetOrCreate ожидает функцию в качестве второго аргумента, но вместо этого вы даете ей результат функции

Ответ №2:

Вы передаете результат вызова функции вместо делегата cacheObject.GetOrCreate() glazingMaterial.AddToOsm(model) это не a Func<T> createItem . Измените все следующим образом:

 using var material = cacheObject.GetOrCreate(glazingMaterial.Id, 
                                             () => glazingMaterial.AddToOsm(model));
  

Это изменение создает анонимный метод с помощью лямбда-выражения, также известного как фабричный метод — это удовлетворит Func<T> createItem параметру, при условии, что glazingMaterial.AddToOsm(model) возвращает допустимый T

Комментарии:

1. здесь возникает проблема, каждый раз, когда я захожу в условие цикла if, где я проверяю наличие «!_cache . Содержит ключ «Key (key)», и не могли бы вы предложить какую-либо идею, почему я каждый раз создаю новый.

2. Поскольку ваш ключ — это a class , который является ссылочным типом — вы просто сравниваете ссылки со значениями в штучной упаковке вместо Id s — если у вас id есть an int , вы должны просто использовать это как ключ или использовать второй общий параметр. Как правило, вы никогда не должны использовать object в качестве ключа