【问题标题】:How do I obtain a list of Collections which contain Objects which Implement an Interface in C# or VB.net如何获取包含在 C# 或 VB.net 中实现接口的对象的集合列表
【发布时间】:2010-08-28 21:43:28
【问题描述】:

我是 .Net 编程的新手,想知道反射是否适合遍历对象以发现类实例中的集合。

我正在使用 Microsoft.SqlServer.Management.Smo 命名空间。

计划是连接到数据库,确定存在哪些集合,然后对于这些集合中的每一个,如果集合公开了实现 IScriptable 接口的对象,则为该对象生成一个脚本。

我如何执行以下操作(这是伪代码,因为我正在寻求使用反射或其他方法来执行以下操作的帮助)

    Imports Microsoft.SqlServer.Management.Smo
    Imports Microsoft.SqlServer.Management.Smo.Agent
    Imports Microsoft.SqlServer.Management.Common

    Dim db as Database
    ...
' 1. How do I determine all Collections in the db Object I have created, which implement the IScriptable Interface.

    For each myCollection as Collection in db.Database.?Collections?
        For each collection_object in myCollection

       If collection_object.GetInterface("IScriptable") IsNot Nothing Then
          ScriptObjectCreate(collection_object, destFolder & "\" & TypeOf(collection_object).toString() & "\", False)
       End If
    Next
Next

到目前为止,我可以通过执行以下操作连接到数据库并编写表格脚本。

For Each obj As Table In db.Tables
                If Not (obj.IsSystemObject) Then
                    ScriptObjectCreate(obj, destFolder & "\" & "Tables\", False)
                End If
Next

我想改变这一点的原因是,不同版本的 SQL Server 将包含不同的对象集合。而不是为每种类型编写代码。

For each obj as Table
For each obj as StoredProcedure 
For each obj as Trigger
etc...

如果可能的话,我想用一个函数枚举数据库中的所有对象

【问题讨论】:

    标签: c# sql-server vb.net reflection smo


    【解决方案1】:

    恐怕这是 C# 而不是 VB.net 但希望你能解释它?

    Server server = new Server();
    Database database = server.Databases["ReportServer"];
    
    foreach (PropertyInfo propertyInfo in typeof(Database).GetProperties())
    {
        if (typeof(SchemaCollectionBase).IsAssignableFrom(propertyInfo.PropertyType))
        {
            SchemaCollectionBase collection = (SchemaCollectionBase)propertyInfo.GetValue(database, null);
    
            foreach (IScriptable item in collection)
            {
                PropertyInfo isSystemObjectPropertyInfo = item.GetType().GetProperty("IsSystemObject");
    
                if (isSystemObjectPropertyInfo == null || !(bool)isSystemObjectPropertyInfo.GetValue(item, null))
                {
                    Console.WriteLine("{0} is scriptable and not a system object", item);
                    // TODO: ScriptObjectCreate(item, destFolder + "\\" + item.GetType() + "\\", false);
                }
            }
        }
    }
    

    关键是使用IsAssignableFrom 来查找集合属性,然后只提取那些实现 IScripable 接口的集合中的对象(因为 SMO 集合不是通用的,所以不可能找到那些包含可编写脚本的对象)。

    【讨论】:

      【解决方案2】:

      听起来你只需要确定一个对象是否实现了给定的接口。如果是这样,那么反思不是正确的工具。相反,您想使用 VB.Net TypeOf 运算符(它是为了这个测试而设计的)。

      If TypeOf collection_object is IScriptable Then 
      

      完整示例

      For each myCollection as Collection in db.Database.Collections
         For each collection_object in myCollection
           if TypeOf collection_object is IScriptable Then ..
            ScriptObjectCreate(collection_object, destFolder & "\" & TypeOf(collection_object).toString() & "\", False)
           End If
         Next
      Next
      

      【讨论】:

      • 你从哪里得到db.Database.Collections?它不在文档中,也不与引用的 SQL Server 2008 R2 SMO 库一起编译。
      • @Daniel,我只是从 OP 的问题中复制了它。我不知道在他们的解决方案中这是否合法。
      • 感谢您的帮助,我将尝试采纳您的建议并发布我的发现。请认识到我的第一个代码项实际上只是伪代码...没有 Database.Collections 我认为这是传达我的想法的最简单方法。感谢您提出任何改进问题的建议。
      猜你喜欢
      • 1970-01-01
      • 2011-03-28
      • 1970-01-01
      • 2012-05-21
      • 1970-01-01
      • 2014-08-25
      • 1970-01-01
      • 1970-01-01
      • 2013-04-12
      相关资源
      最近更新 更多