Как написать функцию С#, которая возвращает тип класса, указанный в качестве параметра?

avatar
Dave
8 августа 2021 в 21:34
93
2
1

Я пытаюсь написать вспомогательный класс JSON для приложения C# MVC, который возвращает экземпляр класса типа, указанного в качестве параметра. Цель этого — упростить десериализацию JSON в модель нужного типа. К сожалению, я столкнулся с ошибкой:

'ModelType' является переменной, но используется как тип.

Вот код, который я использую:


        public ActionResult api_call() {
            // Parse/Map request stream containing a JSON to a C# object
            json_helper _o_json_helper = new json_helper();
            pollread_read_request _request = _o_json_helper.parse_json_to_object(Assembly.GetExecutingAssembly().GetType("pollread_read_request"), Request.InputStream); 
            // Create a business logic instance
            Pollmaker_business_logic _business_logic = new Pollmaker_business_logic();
            // process request using business logic
            List<pollread_read_response> _response = _business_logic.api_call(_request);
            // return result
            return Json(_response, JsonRequestBehavior.AllowGet);
        }

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Reflection;
namespace Umbrella.Abstracts {
    public class json_helper {
        public Object parse_json_to_object(Type ClassModelType, System.IO.Stream InputStream) {
            object _result = Activator.CreateInstance(ClassModelType);
            try {
                string _json_request = "";
                using (System.IO.Stream _oRequestStream = InputStream) {
                    _oRequestStream.Seek(0, System.IO.SeekOrigin.Begin);
                    _json_request = new System.IO.StreamReader(_oRequestStream).ReadToEnd();
                }
                if (!String.IsNullOrEmpty(_json_request)) {
                    _result = Newtonsoft.Json.JsonConvert.DeserializeObject<ClassModelType> (_json_request);
                }
            } catch { }
            return _result;               
        }
        public json_helper() {}
    }
}
Источник
Jimi
8 августа 2021 в 21:48
1

Здесь нельзя использовать дженерики? Например. public T parse_json_to_object<T>(T model, Stream InputStream) where T : class { }. Итак, у вас есть T _result = null; [...] _result = JsonConvert.DeserializeObject<T>(_json_request); Или по какой-то причине у вас нет доступа к типам модели во время выполнения?

Jeroen van Langen
8 августа 2021 в 22:05
0

Небольшое примечание: Другая сторона может создать экземпляр типа, который он отправляет в виде текста. Звучит как возможная дыра в безопасности. Вы должны быть уверены, что он создает только те типы, которые вам разрешены. Где-то был бы полезен набор хэшей с разрешенными типами. своего рода белый список

Dave
8 августа 2021 в 23:13
0

@Джими, иногда у меня нет типов моделей во время выполнения, или они будут скомпилированы из других проектов, у меня нет доступа к созданию эффекта черного ящика.

Jimi
9 августа 2021 в 00:02
0

Это довольно странно. Как узнать, где взять Тип? Assembly.GetExecutingAssembly().GetType("pollread_read_request") недостаточно, чтобы получить тип и создать его экземпляр (кстати, вам действительно не нужно это: object _result = Activator.CreateInstance(ClassModelType); или это: using (System.IO.Stream _oRequestStream = InputStream) { }). АПИ знает?? И что вы собираетесь делать с Объектом, который вы получите обратно? Использовать отражение, чтобы получить имена свойств в виде строк для связующего? -- Если этот дизайн является вашим решением, я бы предложил его перепроектировать.

Ответы (2)

avatar
David L
8 августа 2021 в 21:56
1

Используйте неуниверсальную перегрузку DeserializeObject.

_result = Newtonsoft.Json.JsonConvert.DeserializeObject(_json_request, ClassModelType);
avatar
GoldenAxe
8 августа 2021 в 21:46
0

Вы также пробовали отправлять ему только имя сборки и имя типа?

object _result = Activator.CreateInstance(ClassModelType.Assembly.FullName, ClassModelType.Name);