2011-12-13 3 views
15

값 배열이 주어지면이 값을 기반으로하는 속성을 사용하여 익명 개체를 만들고 싶습니다. 등록 정보 이름은 간단히 "pN" 일 수 있습니다. 여기서 N은 배열 값의 색인입니다. 주어진 예를 들어동적으로 결정된 속성 이름을 사용하여 익명 개체를 만드는 방법은 무엇입니까?

,

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

나는를 사용하는 것입니다

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

내가 생각할 수있는 유일한 방법은이 작업을 수행하는 익명 객체를 생성하고 싶습니다 switch 또는 if 지원할 수있는 합리적인 수의 매개 변수를 연결해야하지만이 작업을 수행하는보다 우아한 방법이 있는지 궁금합니다.

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 
} 

배경

나는 데이터베이스에 대해 SQL 문을 실행할 방법을 기존의 세트가있다. 메서드는 일반적으로 SQL 문에 대해 string을 사용하고 매개 변수가있는 경우 params object[]을 사용합니다. 쿼리가 매개 변수를 사용하는 경우 해당 매개 변수의 이름은 @p0, @p1, @p2, etc.입니다.

예 : 다음과 같이 호출 할 것이다

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

:

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

나는 포장하고 말끔의 Query<T> 방법을 노출하고, 그렇게 할이 클래스에서 Dapper를 사용하고 싶습니다 기존의 방법들, 예를 들면

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

하지만 말끔의 Query<T> 방법은 익명의 객체의 매개 변수 값을 취합니다 : 뭔가처럼

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

단정 한 매개 변수를 전달하기 위해 익명 객체를 만드는 방법에 대한 내 질문에 선도. @Paolo 테 데스 코의 요청에 따라


DynamicParameter 클래스를 사용하여 코드를 추가.

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); 

는 말끔의 SqlMapper.cs 파일의 라인 (581)에서 예외가 발생합니다 :

using (var reader = cmd.ExecuteReader()) 

과를 제외하고는 SqlException입니다 :

은 스칼라 변수 "@ P0"를 선언해야합니다.

을 확인하고 cmd.Parameters 속성을 검사하면 명령에 대해 구성된 매개 변수가 표시되지 않습니다.

+0

예, DynamicParameter를 잘못 사용하고 있습니다 (243 행 참조). http://code.google.com/p/dapper-dot-net/source/browse/Tests/Tests.cs –

+0

또한 'IDynamicParamters'는 적응성. 대용품의 경우 익숙하지 않은 종류의 빵을 구울 필요가 없습니다. 학습 경험으로는 할 수 있지만, 그만한 가치는 없습니다. 특히 emit을 사용하고 싶다면 ICollection에서 강력한 유형을 구울 수 있습니다. –

답변

5

정확히 익명 객체가 아니지만 배열의 값을 기반으로 p1 ... pn에 대한 값을 반환하는 DynamicObject을 구현하는 방법은 무엇입니까? Dapper와 같이 작동합니까?

예 :

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, 고마워,이 위대한지만 불행히도 Dapper는 그것을 좋아하지 않는다 :(. 그것은 전혀 매개 변수없이 db 명령을 실행하려고하는 것을 끝낸다. - 왜 그런지는 아직 모르지만 나는 그것을 평가하려고하고 있다고 생각한다. 매개 변수 값으로 'DynamicParameter' 인스턴스 –

+0

@adrift : 문제를 보여주는 작은 코드 샘플을 게시 할 수 있습니까? –

+0

은'DynamicParameter'를 사용하려고 시도 할 때 생성 된 예외를 보여주는 코드를 포함하도록 질문을 편집했습니다. –

1

당신은 동적으로 익명의 개체를 만들 수 없습니다. 하지만 Dapper는 동적 객체를 사용해야합니다. 좋은 방법으로 동적 객체를 만들려면 Clay을 사용할 수 있습니다. 그것은 당신이

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

당신은 단정을 오용하는 같은 코드를 작성할 수 있습니다, 당신은이 작업을 수행하는 대신 IDynamicParameters를 구현하거나 특정 매우 유연 DynamicParameters 클래스를 사용하거나 할 필요가 없습니다합니다. 특히

:

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 생성자에서 익명 클래스에 걸릴 수 있습니다. AddDynamicParams 메서드를 사용하여 DynamicParameters의 concat을 연결할 수 있습니다.

더 자세히 말하면, anon-types에 대한 엄격한 의존성은 없습니다. 단정은 PARAMS 예를 들어 콘크리트 종류의 수 :

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

... 

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

케빈은 비슷한 질문했다 : Looking for a fast and easy way to coalesce all properties on a POCO- DynamicParameters 작품 완벽하게 여기뿐만 아니라없이 매직 후프 점프에 대한 필요성을.

관련 문제