конвертировать список имен столбцов, чтобы выбрать выражение Lambda [duplicate]

Примером этого исключаемого исключения является: Когда вы пытаетесь проверить что-то, это null.

Например:

string testString = null; //Because it doesn't have a value (i.e. it's null; "Length" cannot do what it needs to do)

if (testString.Length == 0) // Throws a nullreferenceexception
{
    //Do something
} 

Время выполнения .NET исключение NullReferenceException при попытке выполнить действие над чем-то, что не было инстанцировано, т.е. код выше.

По сравнению с ArgumentNullException, которое обычно выбрано как защитная мера, если метод ожидает, что то, что происходит

Дополнительная информация находится в C # NullReferenceException и Null Parameter .

22
задан Richard Hein 18 September 2010 в 07:09
поделиться

2 ответа

Вы близки, но вам нужно знать, что анонимные типы не имеют конструкторов по умолчанию. Следующий код печатает { Name = def, Num = 456 }:

Type anonType = new { Name = "abc", Num = 123 }.GetType();
var exp = Expression.New(
            anonType.GetConstructor(new[] { typeof(string), typeof(int) }),
            Expression.Constant("def"),
            Expression.Constant(456));
var lambda = LambdaExpression.Lambda(exp);
object myObj = lambda.Compile().DynamicInvoke();
Console.WriteLine(myObj);

Если вам не нужно создавать много экземпляров этого типа, Activator.CreateInstance будет делать то же самое (это быстрее для нескольких экземпляров, но медленнее для многих). Этот код печатает { Name = ghi, Num = 789 }:

Type anonType = new { Name = "abc", Num = 123 }.GetType();
object myObj = Activator.CreateInstance(anonType, "ghi", 789);
Console.WriteLine(myObj);
18
ответ дан Gabe 4 September 2018 в 07:57
поделиться

Вы можете избежать использования DynamicInvoke, который очень медленный. Вы можете использовать вывод типа в C #, чтобы получить ваш анонимный тип, созданный в общем виде. Что-то вроде:

public static Func<object[], T> AnonymousInstantiator<T>(T example)
{
    var ctor = typeof(T).GetConstructors().First();
    var paramExpr = Expression.Parameter(typeof(object[]));
    return Expression.Lambda<Func<object[], T>>
    (
        Expression.New
        (
            ctor,
            ctor.GetParameters().Select
            (
                (x, i) => Expression.Convert
                (
                    Expression.ArrayIndex(paramExpr, Expression.Constant(i)),
                    x.ParameterType
                )
            )
        ), paramExpr).Compile();
}

Теперь вы можете позвонить,

var instantiator = AnonymousInstantiator(new { Name = default(string), Num = default(int) });

var a1 = instantiator(new object[] { "abc", 123 }); // strongly typed
var a2 = instantiator(new object[] { "xyz", 789 }); // strongly typed
// etc.

Вы могли бы использовать метод AnonymousInstantiator для генерации функций для создания любого анонимного типа с любым количеством свойств, просто сначала нужно передать соответствующий пример. Входные параметры должны передаваться как массив объектов. Если вы беспокоитесь о производительности бокса, тогда вам нужно написать собственный экземпляр, который принимает только string и int в качестве входных параметров, но использование такого экземпляра будет немного более ограниченным.

6
ответ дан nawfal 4 September 2018 в 07:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: