泛型方法和匿名类型

时间:2014-06-25 07:55:26

标签: c# .net generics

是否可以创建这样的代码:

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

适用于这样的匿名类型:

var point = new { X = 13, Y = 7 };

PS:

输出将是:

INSERT INTO Anonymous (X, Y) values (13, 7)

当然您可能想要提供表名。

4 个答案:

答案 0 :(得分:4)

您无法使用匿名类型指定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())));
}

然后调用方法:var insertString = GetInsertString(new { X = 13, Y = 7 });

答案 1 :(得分:3)

使用...<T>()方法使用匿名类型非常困难。这样做的主要方式是 by example hack,即

var dummy = new { X = 13, Y = 7 };
Foo(dummy); // for Foo<T>(T obj)

或更简洁:

Foo(new { X = 13, Y = 7 });

使用泛型类型推断来推断T这里是匿名类型。 Foo<T>(T obj)

GetInsertString<TDto>()

您也可以将两者结合起来:

// overload that takes an example object as a parameter
private static string GetInsertString<TDto>(TDto example) {
    return GetInsertString<TDto>();
}

并仅在必要时传递示例。

然而,“通过示例”方法是脆弱的并且易于破坏。我强烈建议您只需定义一个POCO:

private static string GetInsertString<TDto>(TDto example = null) {
    .. your code ..
}

并使用public class MyType { public int X {get;set;} public int Y {get;set;} }

答案 2 :(得分:2)

假设您使用的是.net 4.0或更高版本,您可以像这样使用动态和ExpandoObject

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

然后:

dynamic o = new ExpandoObject();

o.a = 10;
o.b = "hello";

var s = GetInsertString(o);

现在sINSERT INTO tableName (a,b) VALUES (10,'hello');。 这只是一个草稿,您必须做一些工作才能获得正确的insert字符串。

答案 3 :(得分:0)

只要编译器可以解析类型,就可以将匿名对象与泛型方法一起使用。例如,如果可以从参数中解析它。像这样:

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