Как я могу использовать отражение, чтобы создать экземпляр класса, который принимает ReadOnlySpan в качестве аргумента конструктора? - PullRequest
1 голос
/ 18 февраля 2020

У меня есть такой код:

    // lookup the object type, instance passing the data as constructor
    //all registered types must implement ctor passed ReadOnlySpan<byte>
    public static object InterpretPayload(ReadOnlySpan<byte> bytes)
    {
        var key = bytes[0];
        if (!TypeLookup.ContainsKey(key))
            return null;
        Type type = TypeLookup[key];
        var created = Activator.CreateInstance(type, bytes);
        return created;
    }

TypeLookup отображает числа c в типы классов в странной манере фабричного метода. Однако, когда я изменяю свою кодовую базу на использование ReadOnlySpan вместо byte[], теперь я получаю ошибку компилятора, что bytes не является объектом, а это не так.

Есть ли другой способ сделать это? Я считаю, что Activator пытается найти лучший ctor, основываясь на том, что я передаю, кажется, мне нужно сделать это более явно. Могу ли я использовать отражение другим способом или я нашел отражение в регистре не может эмулировать вызов ctor напрямую?

1 Ответ

3 голосов
/ 18 февраля 2020

Вы должны использовать отражение, чтобы получить (относительно) делегат со строгой типизацией, чтобы экземпляр ReadOnlySpan можно было передавать без упаковки (что недопустимо для этого типа из-за магического c специального управления временем жизни) )

Начиная с примера для Expression.Parameter :

using System.Linq.Expressions;  

// Creating a parameter for the expression tree.
ParameterExpression param = Expression.Parameter(typeof(ReadOnlySpan<byte>));

// get your type
// get your ConstructorInfo by calling type.GetConstructor(...)

// Creating an expression for the constructor call and specifying its parameter.
var ctorCall = Expression.New(type, ctorinfo, param);


// The following statement first creates an expression tree,
// then compiles it, and then runs it.
var delegateCtor = Expression.Lambda<Func<ReadOnlySpan<byte>,object>>(
ctorCall, new ParameterExpression[] { param }).Compile();

// call it
var created = delegateCtor(bytes);

Возможно, вы захотите кэшировать объект delegateCtor в поиске типа вместо создания его заново. каждый раз.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...