2011-12-13 36 views
15

Với một mảng các giá trị, tôi muốn tạo một đối tượng ẩn danh với các thuộc tính dựa trên các giá trị này. Tên thuộc tính sẽ đơn giản là "pN" trong đó N là chỉ mục của giá trị trong mảng.Cách tạo đối tượng ẩn danh với tên thuộc tính được xác định động?

Ví dụ, cho

object[] values = { 123, "foo" };

Tôi muốn tạo ra các đối tượng ẩn danh

new { p0 = 123, p1 = "foo" };

Cách duy nhất tôi có thể nghĩ ra để làm điều này sẽ được sử dụng một switch hoặc if chuỗi tối đa số lượng thông số hợp lý để hỗ trợ, nhưng tôi đã tự hỏi nếu có một cách thanh lịch hơn để thực hiện việc này:

object[] parameterValues = new object[] { 123, "foo" }; 
dynamic values = null; 

switch (parameterValues.Length) 
{ 
    case 1: 
     values = new { p0 = parameterValues[0] }; 
     break; 
    case 2: 
     values = new { p0 = parameterValues[0], p1 = parameterValues[1] };  
     break; 
    // etc. up to a reasonable # of parameters 
} 

nền

Tôi có một bộ hiện có của phương pháp thực hiện báo cáo sql chống lại một cơ sở dữ liệu. Các phương thức thường lấy một số string cho câu lệnh sql và params object[] cho các tham số, nếu có. Sự hiểu biết là nếu truy vấn sử dụng các thông số, chúng sẽ được đặt tên là @p0, @p1, @p2, etc..

Ví dụ:

public int ExecuteNonQuery(string commandText, CommandType commandType, params object[] parameterValues) { .... } 

đó sẽ được gọi là như thế này:

db.ExecuteNonQuery("insert into MyTable(Col1, Col2) values (@p0, @p1)", CommandType.Text, 123, "foo"); 

Bây giờ tôi muốn sử dụng Dapper trong lớp này để quấn và phơi bày phương pháp Query<T> Dapper, và làm như vậy trong một cách phù hợp với các phương pháp hiện có, ví dụ cái gì đó như:

public IEnumerable<T> ExecuteQuery<T>(string commandText, CommandType commandType, params object[] parameterValues) { .... } 

nhưng phương pháp Query<T> Dapper của mất các giá trị tham số trong một đối tượng ẩn danh:

var dog = connection.Query<Dog>("select Age = @Age, Id = @Id", new { Age = (int?)null, Id = guid }); 

dẫn đến câu hỏi của tôi về việc tạo ra các đối tượng ẩn danh để vượt qua các thông số để Dapper.


Thêm mã bằng cách sử dụng lớp DynamicParameter theo yêu cầu của @Paolo Tedesco.

string sql = "select * from Account where Id = @p0 and username = @p1"; 
dynamic values = new DynamicParameter(123, "test"); 
var accounts = SqlMapper.Query<Account>(connection, sql, values); 

ném một ngoại lệ tại dòng 581 của tập tin SqlMapper.cs Dapper của:

using (var reader = cmd.ExecuteReader()) 

và ngoại lệ là một SqlException:

Phải khai báo các biến vô hướng "@ p0".

và kiểm tra thuộc tính cmd.Parameters không hiển thị thông số nào được định cấu hình cho lệnh.

+0

yeah, bạn đang lạm dụng DynamicParameter, thấy dòng 243: http://code.google.com/p/dapper-dot-net/source/browse/Tests/Tests.cs –

+0

cũng, 'IDynamicParamters' cung cấp cho bạn tuyệt đối Mềm dẻo. Đối với những người lập bản đồ có lợi cho bạn không bao giờ cần phải nướng loại anon, như là một trải nghiệm học tập bạn có thể, nhưng nó không phải là giá trị nỗ lực. Đặc biệt, bạn có thể nướng một loại mạnh mẽ từ một ICollection nếu bạn thực sự muốn sử dụng phát ra. –

Trả lời

5

Không chính xác một đối tượng ẩn danh, nhưng việc triển khai thực hiện DynamicObject trả về giá trị cho p1 ... pn dựa trên các giá trị trong mảng là gì? Điều đó có hiệu quả với Dapper không?

Ví dụ:

using System; 
using System.Dynamic; 
using System.Text.RegularExpressions; 

class DynamicParameter : DynamicObject { 

    object[] _p; 

    public DynamicParameter(params object[] p) { 
     _p = p; 
    } 

    public override bool TryGetMember(GetMemberBinder binder, out object result) { 
     Match m = Regex.Match(binder.Name, @"^p(\d+)$"); 
     if (m.Success) { 
      int index = int.Parse(m.Groups[1].Value); 
      if (index < _p.Length) { 
       result = _p[index]; 
       return true; 
      } 
     } 
     return base.TryGetMember(binder, out result); 
    } 

} 

class Program { 
    static void Main(string[] args) { 
     dynamic d1 = new DynamicParameter(123, "test"); 
     Console.WriteLine(d1.p0); 
     Console.WriteLine(d1.p1); 
    } 
} 
+0

1, cảm ơn, điều này là rất tốt nhưng tiếc là Dapper không thích nó: (Nó kết thúc cố gắng thực thi lệnh db mà không có bất kỳ tham số nào cả - không chắc tại sao, nhưng tôi nghĩ nó đang cố gắng đánh giá Ví dụ 'DynamicParameter' là một giá trị tham số –

+0

@adrift: bạn có thể đăng một mẫu mã nhỏ cho thấy vấn đề của bạn không? –

+0

đã chỉnh sửa câu hỏi để bao gồm mã hiển thị ngoại lệ được tạo khi cố gắng sử dụng' DynamicParameter'. –

1

Bạn có thể không tự động tạo các đối tượng ẩn danh. Nhưng Dapper nên làm việc với đối tượng động. Để tạo các đối tượng động theo một cách tốt đẹp, bạn có thể sử dụng Clay. Nó cho phép bạn viết mã như

var person = New.Person(); 
person["FirstName"] = "Louis"; 
// person.FirstName now returns "Louis" 
12

Bạn đang lạm dụng Dapper, bạn không bao giờ nên cần phải làm điều này, thay vì một trong hai thực hiện IDynamicParameters hoặc sử dụng cực kỳ linh hoạt DynamicParameters lớp học cụ thể.

Đặc biệt:

string sql = "select * from Account where Id = @id and username = @name"; 
var values = new DynamicParameters(); 
values.Add("id", 1); 
values.Add("name", "bob"); 
var accounts = SqlMapper.Query<Account>(connection, sql, values); 

DynamicParameters có thể mất trong một lớp vô danh trong constructor. Bạn có thể concat DynamicParameters bằng phương pháp AddDynamicParams.

Hơn nữa, không có sự phụ thuộc nghiêm ngặt vào loại anon. Dapper sẽ cho phép đối với các loại bê tông như params ví dụ:

class Stuff 
{ 
    public int Thing { get; set; } 
} 

... 

cnn.Execute("select @Thing", new Stuff{Thing = 1}); 

Kevin đã có một câu hỏi tương tự: Looking for a fast and easy way to coalesce all properties on a POCO-DynamicParameters công trình hoàn hảo ở đây cũng không có bất kỳ nhu cầu nhảy hoop kỳ diệu.

Các vấn đề liên quan