我目前正在使用LINQ和C#。
我在LINQ to SQL模型中有一个表的DropDownList。
我希望用户能够从DropDown中选择LINQ表名。在代码中,我想创建一个LINQ类的实例,然后运行Select或它或我想要的任何其他东西。
如何根据用户选择的字符串中的对象名称完成对象的创建?我从一开始就想错了吗?
答案 0 :(得分:6)
您需要Type.GetType(string)和Activator.CreateInstance(Type)。
请注意,Type.GetType(string)只会查找当前正在执行的程序集和mscorlib,除非您指定包括程序集的完整类型名称。在任何一种情况下,您都需要指定包含名称空间的类型名称。
另一种方法是在调用Activator.CreateInstance之前使用Assembly.GetType(string)直接从字符串中获取类型。
(这里实际上有很多的替代品。如果这些都没有帮助你,请发布更多信息,我相信我们可以找到方法。)
答案 1 :(得分:3)
由于您使用ASP.NET标记了帖子,我假设列表位于客户端。如果是这种情况,您应该非常小心地信任该数据,我不建议直接从用户输入创建类型。您可以将数据用作工厂的输入,然后可以返回正确的实例(并根据需要处理任何非法输入)。
答案 2 :(得分:1)
使用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
)等非常棘手,因为构建{{1}}会很曲折。我可能会在那时开始切换到打字模型......
答案 3 :(得分:1)
阐述Brian Rasmussen的警告:类型应该受到限制,需要有意识的设计。优选地,“用户可实例化”类型应标记为可以使用反射验证的特定自定义属性。
答案 4 :(得分:0)
关注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);