我对一个简单问题的长篇描述表示歉意,但我想确保人们正确地理解我想要做的事情。
背景
我正在编写一个工具,它可以读取SqlMetal生成的文件,并创建一个类,该类包含简单的插入、更新、删除和选择方法,然后可以将这些方法公开给web服务。这里的主要优点是,如果表发生了更改,我只需重新运行该工具,与数据库相关的代码就会自动更新,使用它的任何地方都会生成编译错误,因此很容易跟踪需要进行手动更改的地方。例如,如果我有一个Customer表,其中包含以下字段:
我希望能够生成插入和删除方法如下:
// 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生成一个客户类。现在,我要做的是将这个.cs文件读入我的新工具中,以便用上面的方法创建另一个类。然后,可以将这个新类公开给web服务,以授予对此功能的访问权,而不必公开底层数据库。我正在使用NRefactory读取SqlMetal生成的文件,到目前为止,它运行良好,但在读取客户类上的属性时遇到了困难。
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’的私有变量,它包含了我想要的所有参数的列表,但我无法通过代码访问它。
如何获得这个“未解决”变量的内容?我还需要用Resolver做点什么吗?这是我第一次使用NRefactory,所以我还不太熟悉所有的细微差别。我一直很难找到一个深入到谷歌这个层次的例子,我为NRefactory所看到的文档似乎没有涵盖它。任何帮助都将不胜感激。
发布于 2013-07-25 15:50:22
我想通了。在解析System.Data.Linq之前,我需要将IProjectContent的程序集加载到SyntaxTree中。
...
CecilLoader loader = new CecilLoader();
Assembly[] assembliesToLoad = {
...
typeof(System.Data.Linq.Mapping.ColumnAttribute).Assembly
...};
IUnresolvedAssembly[] projectAssemblies = new IUnresolvedAssembly[assembliesToLoad.Length];
for(int i = 0; i < assembliesToLoad.Length; i++)
{
projectAssemblies[i] = loader.LoadAssemblyFile(assembliesToLoad[i].Location);
}
IProjectContent project = new CSharpProjectContent();
project = project.AddAssemblyReferences(projectAssemblies);
...https://stackoverflow.com/questions/17840420
复制相似问题