Динамически подключать класс, имеющий разные возможные конструкторы - PullRequest
0 голосов
/ 02 июня 2011

Скажем, у меня есть два класса, которые выглядят так:

public class ByteFilter
{
    private Func <int, byte[]> readBytes;
    private Action<byte[]> writeBytes;

    public ByteFilter(Func <int, byte[]> readBytes, Action<byte[]> writeBytes)
    {
        this.readBytes = readBytes;
        this.writeBytes = writeBytes;
    }
}

public class PacketFilter
{
    private Func<Packet> readPacket;
    private Action<Packet> writePacket;

    Public PacketFilter(Func<Packet> readPacket, Action<Packet> writePacket)
    {
        this.readBytes = readPacket;
        this.writeBytes = writePacket;
    }
}

Каждый класс может быть создан во время выполнения (через Activator.CreateInstance) для выполнения функции фильтрации.Методы чтения и записи будут подключены во время выполнения к методам из других классов, которые будут предоставлять и принимать байтовые массивы или пакеты.

Внутри каждого фильтра есть дополнительный код, который выполняет функцию фильтрации:

public void Process()
{
    while (!done)
    {
        byte[] data = ReadBytes();      // or ReadPacket()
        // perform filtering on data
        WriteBytes(data);               // or WritePacket()
    }
}

Если только одна из вышеуказанных сигнатур конструктора будет присутствовать в каждом фильтре, как определить (используя Reflection) какая сигнатура конструктора присутствует, чтобы я мог подключить соответствующие методы во время выполнения?

Примечание: если я глупый и делаю это неправильно, я бы тоже хотел это знать.

Ответы [ 3 ]

2 голосов
/ 02 июня 2011

Разве вы не можете сделать что-то подобное?

bool packetConstructor = 
            typeof(PacketFilter).GetConstructors()
                                .Any(c => c.GetParameters()
                                           .Any(p => p.ParameterType 
                                                    == typeof(Func<Packet>)));

заменив typeof(PacketFilter) соответствующим экземпляром.

2 голосов
/ 05 июня 2011

Опция, которая не была упомянута, заключается в использовании Fasterflect , библиотеки, созданной для того, чтобы сделать отражение более легким и быстрым, где это возможно.

Он также имеет несколько функций, построенных на основе основных возможностей отражения, одной из которых является возможность создавать объекты, когда вы не знаете, какие конструкторы доступны.

var instance = typeof(PacketFilter).TryCreateInstance( new { Foo = "Bar" } );

Существуют также перегрузки для передачи в словарь именованных значений или дискретных массивов имен и значений. Последний код также предоставляет расширения для создания объектов только из упорядоченного списка значений, сопоставляя их в соответствии с параметрами по их типу.

Fasterflect автоматически выберет конструктор с наиболее подходящими аргументами. Если он не может использовать значение, он попытается установить соответствующее свойство после построения. И у вас есть возможность требовать использования всех значений.

Отказ от ответственности: я участник проекта.

1 голос
/ 02 июня 2011

Вы можете перечислить конструкторы (чтобы получить один конструктор), а затем перечислить параметры конструктора.Поскольку ожидается, что параметры являются универсальными типами, вам необходимо перечислить параметры универсального типа для каждого параметра универсального конструктора.Обратите внимание, что все это очень забавно, и я бы порекомендовал найти лучшее решение.Отражение является мощным инструментом, и его использование представляет сложность;если есть менее сложное решение (например, фабричный шаблон), это было бы предпочтительным.Также возможно, что ваша потребность в решении этой конкретной проблемы отражает чрезмерную сложность существующего дизайна.Если вы упростите оригинальный дизайн, вы можете обнаружить, что техническая проблема исчезла.

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