是否可以使用 class 的属性而不了解它(甚至是类型和名称)?
Is it possible to use class's properties not knowing anything about it (even a type and name)?
我想尽量不要用带有SQL语句的类似代码编写所有方法和classes,并遵循DRY原则。现在我需要访问未知 class.
的属性
public T Get(string pathToClass, string sqlStatement)
{
SqlConnection connection = new SqlConnection();
connection.ConnectionString = connectionString; //connectionString is field of class.
connection.Open();
SqlCommand command = new SqlCommand(sqlStatement);
SqlDataReader reader = command.ExecuteReader();
List<Type> types = new Reflect(pathToClass).GetTypes(); //Reflection is my class library
List<string> names = new Reflect(pathToClass).GetNames(); //it only reads the classes and returns properties's names and types.
object entity = new object(); //idk is it right or not, but seems it is.
for(int i = 0; reader.Read(); i++)
{
entity.SomeProperty = types[i].Parse(reader[names[i]].ToString()); //There is a wrong point, where I'm confused
}
connection.Close();
return (T)entity;
}
如果不使用 ORM,这里常用的方法是返回原始 DataRow
或 IDataRecord
对象,使用静态工厂方法和 each/all 您的个人类型知道如何给定 IDataRecord
或 DataRow
输入构造该类型的实例。
例如:
//Initial class might look like this:
public class Employee
{
public string FirstName {get;set;}
public string LastName {get;set;}
public int ID {get;set;}
public string Email {get;set;}
public static Employee FromDataRow(DataRow row)
{
return new Employee
{
ID = row["ID"],
FirstName = row["FirstName"],
LastName = row["LastName"],
Email = row["Email"]
};
}
}
//Data access might look like this:
public class DB
{
private static string ConnectionString { get;} = "connection string here";
public static IEnumerable<DataRow> FindEmployeeRecords(string LastName)
{
string sql = "SELECT ID, FirstName, LastName, Email FROM Employee WHERE LastName LIKE @LastName + '%'";
using (var cn = new SqlConnection(ConnectionString))
using (var cmd = new SqlCommand(sql, cn))
using(var da = new SqlDataAdapter(cmd))
{
cmd.Parameters.Add("@LastName", SqlDbType.NVarChar, 80).Value = LastName;
var result = new DataSet();
da.Fill(result);
return results.Tables[0].Rows;
}
}
}
// and then you could use it like this:
var employees = DB.FindEmpoyeeRecords("Smith").Select(Employee.FromDataRow);
foreach (var employee in employees)
{
//...
}
// or you could bind employees to a datasource
当然,您可以使用reflection将数据行字段映射到对象。您甚至可以将其中的一部分抽象为实用方法。但是,您仍然需要每种类型的工厂方法(只是代码少了一点),反射是 slow (就像,真的很慢),并且您失去了映射方式的灵活性如果您希望 class 字段与 table 列稍有不同,就会发生这种情况。
我们也可以reduce boilerplate code in the database layer。但是,这需要对函数式编程有更好的理解。
我想尽量不要用带有SQL语句的类似代码编写所有方法和classes,并遵循DRY原则。现在我需要访问未知 class.
的属性public T Get(string pathToClass, string sqlStatement)
{
SqlConnection connection = new SqlConnection();
connection.ConnectionString = connectionString; //connectionString is field of class.
connection.Open();
SqlCommand command = new SqlCommand(sqlStatement);
SqlDataReader reader = command.ExecuteReader();
List<Type> types = new Reflect(pathToClass).GetTypes(); //Reflection is my class library
List<string> names = new Reflect(pathToClass).GetNames(); //it only reads the classes and returns properties's names and types.
object entity = new object(); //idk is it right or not, but seems it is.
for(int i = 0; reader.Read(); i++)
{
entity.SomeProperty = types[i].Parse(reader[names[i]].ToString()); //There is a wrong point, where I'm confused
}
connection.Close();
return (T)entity;
}
如果不使用 ORM,这里常用的方法是返回原始 DataRow
或 IDataRecord
对象,使用静态工厂方法和 each/all 您的个人类型知道如何给定 IDataRecord
或 DataRow
输入构造该类型的实例。
例如:
//Initial class might look like this:
public class Employee
{
public string FirstName {get;set;}
public string LastName {get;set;}
public int ID {get;set;}
public string Email {get;set;}
public static Employee FromDataRow(DataRow row)
{
return new Employee
{
ID = row["ID"],
FirstName = row["FirstName"],
LastName = row["LastName"],
Email = row["Email"]
};
}
}
//Data access might look like this:
public class DB
{
private static string ConnectionString { get;} = "connection string here";
public static IEnumerable<DataRow> FindEmployeeRecords(string LastName)
{
string sql = "SELECT ID, FirstName, LastName, Email FROM Employee WHERE LastName LIKE @LastName + '%'";
using (var cn = new SqlConnection(ConnectionString))
using (var cmd = new SqlCommand(sql, cn))
using(var da = new SqlDataAdapter(cmd))
{
cmd.Parameters.Add("@LastName", SqlDbType.NVarChar, 80).Value = LastName;
var result = new DataSet();
da.Fill(result);
return results.Tables[0].Rows;
}
}
}
// and then you could use it like this:
var employees = DB.FindEmpoyeeRecords("Smith").Select(Employee.FromDataRow);
foreach (var employee in employees)
{
//...
}
// or you could bind employees to a datasource
当然,您可以使用reflection将数据行字段映射到对象。您甚至可以将其中的一部分抽象为实用方法。但是,您仍然需要每种类型的工厂方法(只是代码少了一点),反射是 slow (就像,真的很慢),并且您失去了映射方式的灵活性如果您希望 class 字段与 table 列稍有不同,就会发生这种情况。
我们也可以reduce boilerplate code in the database layer。但是,这需要对函数式编程有更好的理解。