将 List<object> 转换为 List<model> 仅使用模型名称 C# MVC 键入

Convert List<object> to List<model> type with only the model name c# mvc

提问人:Manib 提问时间:5/3/2023 最后编辑:Manib 更新时间:5/4/2023 访问量:182

问:

所以我正在尝试创建一个泛型函数(目前不是,但我想在未来证明它,所以在以后的阶段可以选择/传递 tableName)。

我想使用字符串来获取模型并使变量为类型,但我一直在获取类型。Customers_ModelcCustomers_Modelobject

我知道你可以做到:但这假设你知道该模型类型,但我只从字符串中获取了模型类型。我觉得好像与变量有关,因为它包含模型名称,但不能完全理解它。(Customers_Model)Activator.CreateInstance(type)type

我也看到过这一点,但它假设您知道要在模型中访问的函数。在这种情况下,我们不知道其中的任何函数/字段来使用此解决方案,只有 .modelName

        public async Task<ActionResult> Index()
        {
            var tableName = "Customers";
            string modelName = "MVC.Models." + tableName + "_Model";
            Type type = Type.GetType(modelName);
            var d = Activator.CreateInstance(type);
            var c = Convert.ChangeType(d, type);
            var data = await DBServices.GetFromTable(tableName, c);
            if (data.Count > 0)
            {
                return View(data);
            }
            else 
                return View();
        }

编辑 1

我希望用户选择一个表,然后让它在视图中显示该表。My View 接受模型GeneralViewModel

GeneralViewModel:

    public class GeneralViewModel
    {
        public List<Customers_Model> Customers {get; set;}
    }

在稍后的阶段,我希望能够添加更多模型,而不必更改控制器/视图,因为它已经泛化了。

我是否应该转换为一个,当它显示在视图中时,然后只查找计数> 0 的第一个列表并将其显示?我只希望一次填充一个列表。cGeneralViewModelGeneralViewModel

编辑 2

这是我的 DBServices 中的几个函数,因为发送的 T 类型是 object(由于上面的 var c),那么返回类型也是 object。如果我能整理出传入的类型,那么这一切都将得到解决。

        public static async Task<List<T>> GetFromTable<T>(string tableName, T type)
        {
            var results = new List<T>();
            using (SqlConnection conn = new SqlConnection(connectionString))
            {
                string cmdText = "SELECT * FROM " + tableName + ";";

                SqlCommand cmd = new SqlCommand(cmdText, conn);
                try
                {
                    conn.Open();
                    SqlDataReader reader = await cmd.ExecuteReaderAsync();

                    while (reader.Read())
                    {
                        if (reader != null)
                        {
                            results.Add(ConvertReader((IDataReader)reader, type));
                        }
                    }
                    reader.Close();
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }
            return results;
        }

        public static T ConvertReader<T>(IDataReader reader, T value)
        {
            //var item = value;
            var typeProperties = value.GetType().GetProperties();

            foreach (var property in typeProperties)
            {
                DisplayNameAttribute attr = (DisplayNameAttribute)Attribute.GetCustomAttribute(property, typeof(DisplayNameAttribute));

                int ordinal;
                if (attr != null)
                {
                    ordinal = reader.GetOrdinal(attr.DisplayName);
                }
                else
                {
                    ordinal = reader.GetOrdinal(property.Name);
                }

                if (!reader.IsDBNull(ordinal))
                {
                    property.SetValue(value, reader[ordinal], null);
                }
            }

            return value;
        }
C# 对象 类型 强制转换 typeof

评论

1赞 Olivier Jacot-Descombes 5/3/2023
Convert.ChangeType在这里是无用的,因为它返回一个 ,就像一样。但是,即使您设法将数据转换为强类型列表,您如何将其传递给正确的方法呢?请注意,泛型类型始终在编译时解析。它们在动态场景中根本没有帮助。只需针对非泛型接口即可。objectActivator.CreateInstanceIList
3赞 JonasH 5/3/2023
您要解决的实际问题是什么?泛型是 C# 中的编译时概念,如果您在运行时定义表名,您将寻找“反射”,虽然这有时很有用,但它通常会变得难以维护的不可读的混乱。碰巧的是,“未来证明”有时也用于难以维护的不可读代码。
0赞 MakePeaceGreatAgain 5/3/2023
如果你想通过名称获取一个类型,你可以使用 ,如下所示:stackoverflow.com/questions/20008503/get-type-by-name。然而,正如 JonasH 所提到的,除了使用反射之外,你永远不会得到任何不同的东西,你需要转换为编译时类型,这使得整个事情变得非常毫无意义。Type.GetTypeobject
0赞 MakePeaceGreatAgain 5/3/2023
你能提取一个所有实体实现的通用接口吗?
0赞 Manib 5/3/2023
不,我不能。它们中都有不同的字段,在编译时我不知道用户正在选择哪个表,所以我不知道哪些字段可用

答:

0赞 DonMiguelSanchez 5/3/2023 #1

您是否尝试过模式匹配?

    using System;
    using System.Collections.Generic;
    using System.Globalization;
    using System.Linq;
    using System.Reflection;
    using System.Text;
    using System.Threading.Tasks;

namespace StackOverflow
{
    internal class Program
    {
        static void Main(string[] args)
        {

            List<int> a = GetList(10, 10);
            List<double> b = GetList(10, 100.0);
            List<ModelTest> c = GetList(10, new ModelTest());
           
        }

        private static List<T> GetList<T>(int numberOfElements, T value)
        {
            Type type = typeof(T);

            var actualInstance = Activator.CreateInstance(type);

            actualInstance = value;

            var list = new List<T>();

            for (int i = 0; i < numberOfElements; i++)
            {
                if (actualInstance is T t)
                {
                    list.Add(t);
                }
            }

            return list;
        }

    }
    internal class ModelTest
    {
       public ModelTest()
       {

       }
    }
}

这编译并返回预期的结果,这是一个简单的示例,还有一些东西需要添加,如果类型不包含无参数构造函数,它会带来异常,当然你可以避免改进方法。TGetList()

这是你需要的吗?,我在这里错过了什么吗?

问候

米格尔·:)

0赞 Manib 5/4/2023 #2

我最终只是创建了一个用于将字符串转换为模型类型的工具。然后,我将其作为第二个参数传递到函数中。然后它返回了正确的结果。Dictionary<string, dynamic>GetFromTable