我正在开发一个庞大的旧项目,其中包含许多脆弱的代码,其中一些代码自.NET 1.0时代开始就已存在,并且已经并将由其他人工作......所以我我想尽可能少地改变。
我的解决方案中有一个包含DataSet.xsd的项目。该项目编译为单独的程序集(Data.dll)。数据库模式包括或多或少按层次排列的几个表,但表实际链接在一起的唯一方法是通过连接。我可以得到,例如自动生成的代码中的DepartmentRow
和EmployeeRow
个对象。 EmployeeRow
包含来自员工对应的DepartmentRow
通过加入的信息。
我正在制作一份新报告,以查看多个部门及其所有员工。如果我使用现有的数据访问方案,我将能够获得的是类似电子表格的输出,其中每个员工在一行上表示,部门信息在其相应的列中反复重复。 E.g:
Department1...Employee1...
Department1...Employee2...
Department2...Employee3...
但客户想要的是让每个部门都像标题一样呈现,每个部门下面都有员工列表。 E.g:
- Department1...
Employee1...
Employee2...
+ Department2...
我正在尝试通过从自动生成的Row对象继承层次结构对象来实现此目的。 E.g:
public class Department : DataSet.DepartmentRow {
public List<Employee> Employees;
}
通过使用Department对象的集合作为DataSource,我可以将数据嵌套在报表中,每个对象都将其Employees列表放在子报表中。
问题是这给了我The type Data.DataSet.DepartmentRow has no constructors defined
错误。当我尝试构建一个构造函数时,例如
public class Department : DataSet.DepartmentRow {
private Department() { }
public List<Employee> Employees;
}
除第一个错误外,我收到'Data.DataSet.DepartmentRow(System.Data.DataRowBuilder)' is inaccessible due to its protection level.
错误。
有没有办法完成我想要做的事情?或者还有其他我应该完全尝试的东西吗?
答案 0 :(得分:4)
我能够在快速测试中继承数据行。请注意,这与数据行类位于同一程序集中。数据行类的构造函数标记为“内部”。
using System;
using System.Data;
namespace Blah
{
/// <summary>
/// Summary description for Class1.
/// </summary>
public class Class1 : MyDataSet.MyTableRow
{
public Class1(DataRowBuilder rb) : base(rb)
{
//
// TODO: Add constructor logic here
//
}
}
}
答案 1 :(得分:2)
我不确定装配布局是什么。如果新的继承类型驻留在“Data.dll”之外,并且您需要访问内部构造函数...假设您仍然可以更改此程序集,则可以尝试添加“InternalsVisibleToAttribute”(http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.internalsvisibletoattribute.aspx)。希望这可以帮助。
答案 2 :(得分:1)
我最终找到了一个具有以下好处的解决方法:
在数据集的代码隐藏文件(DataSet.cs,通过扩展DataSet.xsd在VS2008中访问)中,我添加了一个新的部分类定义,它添加了一个具有不同签名的公共构造函数,但在功能上与现有的内部构造函数:
public partial class DataSet {
public partial class DepartmentRow {
public DepartmentRow(global::System.Data.DataRowBuilder rb, string discard) : this(rb) { }
}
public partial class EmployeeRow {
public EmployeeRow(global::System.Data.DataRowBuilder rb, string discard) : this(rb) { }
}
}
然后,我可以在派生类中使用此构造函数:
public class Department : DataSet.DepartmentRow {
public Department(global::System.Data.DataRowBuilder DataRowBuilder rb) : base(rb, "discard") { }
public List<Employee> Employees;
public string[] SomeFrequentlyUsedGroupOfFields {
get {
return new string[] { this.OneField, this.AnotherField };
}
}
public bool CanUserSeeDepartmentInformation(int UserID) { }
}
瞧!
不幸的是,在实现这个结果之后,我意识到它并没有多大用处,因为DataSetTableAdapters.DepartmentTableAdapter
中自动生成的代码仍然返回DataSet.DepartmentRow
类型的对象,我不得不向下转换来获取我的具有额外属性/方法的Department
对象。这是不允许的,我无法轻易解决这个问题。
我可以将所有新成员移动到部分类代码隐藏,但我不确定哪些架构规范会违反。 (似乎有一些任意应用数据逻辑和业务逻辑之间的区别。)