简体   繁体   English

泛型方法和匿名类型

[英]generic method and anonymous types

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: PS:

Output would be: 输出将是:

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

of course you may want to provide the table name. 当然你可能想提供表名。

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: 您将无法使用匿名类型指定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 }); 然后调用方法: var insertString = GetInsertString(new { X = 13, Y = 7 });

It is very hard to use anonymous types with a ...<T>() method. 使用带有...<T>()方法的匿名类型非常困难。 The main way of doing that involves the by example hack, ie 这样做的主要方式涉及例如黑客,即

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. 它使用泛型类型推断来推断出这里的T是匿名类型。 Foo<T>(T obj) could either be your actual method, or could be a method that in turn calls GetInsertString<TDto>() , ie 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>();
}

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: 我强烈建议您只需定义一个POCO:

public class MyType {
    public int X {get;set;}
    public int Y {get;set;}
}

and use GetInsertString<MyType> . 并使用GetInsertString<MyType>

Assuming you're using .net 4.0 or above, you can use dynamic and ExpandoObject like this: 假设您使用的是.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())));
}

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'); 现在sINSERT INTO tableName (a,b) VALUES (10,'hello'); . This is only a draft you have to do some work to get a correct insert string. 这只是一个草稿,您必须做一些工作才能获得正确的insert字符串。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM