【问题标题】:Can I start with a string and instantiate an object of that string?我可以从一个字符串开始并实例化该字符串的一个对象吗?
【发布时间】:2009-07-16 18:46:31
【问题描述】:

我目前正在使用 LINQ 和 C#。

我的 LINQ to SQL 模型中有一个表的 DropDownList。

我希望用户能够从下拉列表中选择一个 LINQ 表名。在代码中,我想创建该 LINQ 类的实例,然后运行 ​​Select 或它或我想要的任何其他东西。

如何根据用户选择的字符串中的对象名称创建对象?我是不是一开始就想错了?

【问题讨论】:

    标签: c# .net asp.net linq-to-sql


    【解决方案1】:

    你想要Type.GetType(string)Activator.CreateInstance(Type)

    请注意,Type.GetType(string) 只会在当前执行的程序集和 mscorlib 中查找,除非您指定包括程序集在内的完整类型名称。无论哪种情况,您都需要指定类型名称,包括命名空间。

    另一种方法是在调用 Activator.CreateInstance 之前使用Assembly.GetType(string) 直接从字符串中获取类型。

    (这里实际上有 很多 种替代方法。如果这些方法都不能帮助您,请发布更多信息,我相信我们可以找到解决方法。)

    【讨论】:

      【解决方案2】:

      由于您使用 ASP.NET 标记了帖子,我假设该列表位于客户端。如果是这种情况,您应该非常小心地信任该数据,并且我不建议直接从用户输入创建类型。您可以将数据用作工厂的输入,然后该工厂可以返回正确的实例(并在您认为合适的情况下处理任何非法输入)。

      【讨论】:

        【解决方案3】:

        详细阐述 Brian Rasmussen 的警告:类型应该受到限制并且需要有意识的设计。最好是“用户可实例化”类型应使用可以通过反射验证的特定自定义属性进行标记。

        【讨论】:

          【解决方案4】:

          对于 LINQ-to-SQL,有一些特定的方法可以从数据上下文中执行此操作;基本上,db.GetTable。这将返回一个ITable,但使用无类型的ITable 有点棘手。至少你可以列举出来……

          要获得ITable,您通常需要Type,您可以通过(例如)Assembly.GetType 获得:

              using (var ctx = new MyDataContext()) {
                  string name = "Customer"; // type name
                  Type ctxType = ctx.GetType();
                  Type type = ctxType.Assembly.GetType(
                      ctxType.Namespace + "." + name);
                  ITable table = ctx.GetTable(type);
                  foreach(var row in table) {
                      Console.WriteLine(row); // works best if ToString overridden...
                  }
              }
          

          当然,一旦你有了Type,你就可以使用Activator来创建新的实体实例:

                  object newObj = Activator.CreateInstance(type);
                  // TODO: set properties (with reflection?)
                  table.InsertOnSubmit(newObj);
          

          但如果您想使用属性名称,那也可以:

              using (var ctx = new MyDataContext()) {
                  string name = "Customers"; // property name
                  ITable table = (ITable) ctx.GetType()
                      .GetProperty(name).GetValue(ctx, null);
                  foreach (var row in table) {
                      Console.WriteLine(row); // works best if ToString overridden...
                  }
              }
          

          运行过滤器 (Where) 等对于无类型数据来说是很棘手的,因为构建 Expression 会很曲折。那时我可能会开始切换到类型化模型...

          【讨论】:

            【解决方案5】:

            跟随 Marc Gravell 的回答。

            按照他的建议,我注意到了一个 Cast<TResult> 扩展方法(在 System.Linq 中定义)。

            不幸的是,您似乎无法使用 type 实例进行投射:

            Type dcType = dc.GetType();
            Type type = dcType.Assembly.GetType(String.Format("{0}.{1}", dcType.Namespace, name));
            var row = dc.GetTable(type).Cast<type>().SingleOrDefault(i => i.ID == 123);
            

            【讨论】:

            猜你喜欢
            • 2012-12-23
            • 2020-11-28
            • 2010-10-07
            • 2016-06-24
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多