对于一个简单问题的冗长描述,我提前道歉,但我想确保人们正确理解我正在尝试做的事情。
背景
我正在编写一个工具,它可以读取 SqlMetal 生成的文件并创建一个包含简单插入、更新、删除和选择方法的类,然后可以将其公开给 Web 服务。这里的主要优点是,如果表发生更改,我只需重新运行该工具,数据库相关代码就会自动更新,并且在任何使用它的地方都会产生编译错误,从而可以轻松追踪需要手动更改的地方做出来。例如,如果我有一个包含以下字段的 Customer 表:
- CustomerId(PK,身份)
- 名
- 姓
我希望能够生成插入和删除方法,如下所示:
// I only want non-database-generated fields to be parameters here.
public static Customer InsertCustomer(String firstName, String lastName)
{
...
}
// I only want the primary key fields to be parameters here.
public static int DeleteCustomer(int customerId)
{
...
}
我正在使用 SqlMetal 生成一个 Customer 类。现在我要做的是将该 .cs 文件读入我的新工具中,以便使用上述方法创建另一个类。然后可以将这个新类公开给 Web 服务,以授予对该功能的访问权限,而无需公开底层数据库。我正在使用 NRefactory 读取 SqlMetal 生成的文件,到目前为止,一切顺利,但我在尝试读取 Customer 类的属性时遇到了障碍。
SqlMetal 使用 ColumnAttribute 生成其类,以标识从数据库列派生的每个属性。ColumnAttribute 将有许多参数来描述数据库列的属性。在上面的示例中,它将生成如下内容:
...
[Column(Name="customerId", Storage="_CustomerId, DbType="INT NOT NULL IDENTITY", IsPrimaryKey=true, IsDbGenerated=true)]
public int CustomerId
{
...
}
[Column(Name="firstName", Storage="_FirstName", DbType="NVarChar(100) NOT NULL", CanBeNull=false)]
public String FirstName
{
...
}
[Column(Name="lastName", Storage="_LastName", DbType="NVarChar(100) NOT NULL", CanBeNull=false)]
public String LastName
{
...
}
...
问题
如您所见,SqlMetal 为我提供了我需要的属性,以便识别哪些列是数据库生成的,哪些列是主键的一部分。因此,当我将该文件读入 NRefactory 并解析类型时,我希望能够获得所有这些信息。但是,我发现虽然我可以访问 ColumnAttribute,但其上的所有参数都未解析,因此无法通过 NamedArguments 或 PositionalArguments 属性访问。
这是我的代码:
SyntaxTree syntaxTree = ...;
foreach(AstNode tableNode in syntaxTree.Children)
{
ResolveResult result = resolver.Resolve(tableNode);
var properties = result.Type.GetProperties();
foreach (IProperty p in properties)
{
var attributes = p.Attributes;
bool isPrimaryKeyField = false;
bool isDbGenerated = false;
bool isColumn = false;
foreach (IAttribute attr in attributes)
{
if (attr.AttributeType.Name == "Column")
{
isColumn = true;
foreach (var arg in attr.NamedArguments) // NamedArguments contains no items.
{
if (arg.Key.Name == "IsPrimaryKey")
{
isPrimaryKeyField = (bool)arg.Value.ConstantValue == true;
}
if (arg.Key.Name == "IsDbGenerated")
{
isDbGenerated = (bool)arg.Value.ConstantValue == true;
}
}
}
}
if (isColumn)
{
... // Create a parameter as appropriate.
}
}
}
这一切都有效,直到我尝试遍历 IAttribute.NamedArguments 因为集合不包含任何元素。但是,当我通过调试器并检查“attr”的值时,我可以看到有一个名为“unresolved”的私有变量,其中包含我想要的所有参数的列表,但我找不到访问它的方法通过代码。
如何获取此“未解析”变量的内容?我需要用解析器做更多的事情吗?这是我第一次使用 NRefactory,所以我还不太熟悉所有的细微差别。我一直很难在 Google 上找到一个深入这种深度的示例,而我为 NRefactory 看到的文档似乎没有涵盖它。任何帮助,将不胜感激。