Reputation: 17408
Would it be possible to create code like this:
private static string GetInsertString<TDto>()
{
var type = typeof(TDto);
var properties = type.GetProperties().Where(Where);
var tableName = type.Name;
return string.Format("INSERT INTO {0} ({1}) VALUES ({2});",
tableName,
string.Join(",", properties.Select(x => x.Name).ToArray()),
string.Join(",", properties.Select(x => string.Format("@{0}", x.Name.ToLower())).ToArray()));
}
that works with anonymous types like this:
var point = new { X = 13, Y = 7 };
PS:
Output would be:
INSERT INTO Anonymous (X, Y) values (13, 7)
of course you may want to provide the table name.
Upvotes: 7
Views: 3354
Reputation: 8868
Assuming you're using .net 4.0 or above, you can use dynamic and ExpandoObject
like this:
private static string GetInsertString(dynamic obj)
{
var expando = (ExpandoObject)obj;
return string.Format("INSERT INTO {0} ({1}) VALUES ({2});",
"tableName",
string.Join(",", expando.Select(x => x.Key)),
string.Join(",", expando.Select(x => x.Value is string ? "'" + x.Value + "'" : x.Value.ToString())));
}
And then:
dynamic o = new ExpandoObject();
o.a = 10;
o.b = "hello";
var s = GetInsertString(o);
Now s
is INSERT INTO tableName (a,b) VALUES (10,'hello');
.
This is only a draft you have to do some work to get a correct insert
string.
Upvotes: 2
Reputation: 18102
You won't be able to specify the type parameter with an anonymous type, but if you pass it an object as a parameter, you can use type inference to get a hold of the type:
private static string GetInsertString<TDto>(TDto dto)
{
var type = typeof(TDto);
var propertyNames = type.GetProperties().Where(Where).Select(x => x.Name);
return string.Format("INSERT INTO {0} ({1}) VALUES ({2});",
type.Name,
string.Join(",", propertyNames),
string.Join(",", propertyNames.Select(x => string.Format("@{0}", x.ToLower())));
}
Then call the method: var insertString = GetInsertString(new { X = 13, Y = 7 });
Upvotes: 4
Reputation: 1062965
It is very hard to use anonymous types with a ...<T>()
method. The main way of doing that involves the by example hack, i.e.
var dummy = new { X = 13, Y = 7 };
Foo(dummy); // for Foo<T>(T obj)
or more succinctly:
Foo(new { X = 13, Y = 7 });
which uses generic type inference to deduce that T
here is the anonymous type. Foo<T>(T obj)
could either be your actual method, or could be a method that in turn calls GetInsertString<TDto>()
, i.e.
// overload that takes an example object as a parameter
private static string GetInsertString<TDto>(TDto example) {
return GetInsertString<TDto>();
}
You could also probably combine the two:
private static string GetInsertString<TDto>(TDto example = null) {
.. your code ..
}
and pass the example only when it is necessary.
However, the "by example" approach is brittle and susceptible to breaking. I strongly recommend that you simply define a POCO instead:
public class MyType {
public int X {get;set;}
public int Y {get;set;}
}
and use GetInsertString<MyType>
.
Upvotes: 3
Reputation: 22945
You can use anonymous objects with generic methods as long as the compiler can resolve the type. For instance, if it can be resolved from a parameter. Like this:
private static string GetInsertString<TDto>(TDto someObject) {
var type = typeof(TDto);
var properties = type.GetProperties(); // Removed .Where(Where) since it didn't compile
var tableName = type.Name;
return string.Format(
"INSERT INTO {0} ({1}) VALUES ({2});",
tableName,
string.Join(",", properties.Select(x => x.Name).ToArray()),
string.Join(",", properties.Select(x => string.Format("@{0}", x.Name.ToLower())).ToArray())
);
}
var point = new { X = 13, Y = 7 };
var insertSql = Test.GetInsertString(point);
// Results in: INSERT INTO <>f__AnonymousType0`2 (X,Y) VALUES (@x,@y);
Upvotes: 0