动态连接具有不同可能构造函数的类

发布于 2024-11-13 12:17:23 字数 1112 浏览 3 评论 0原文

假设我有两个如下所示的类:

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

如果每个过滤器中仅存在上述构造函数签名之一,我如何确定(使用反射)存在哪个构造函数签名,以便我可以在运行时连接适当的方法吗?

注意:如果我很愚蠢并且以错误的方式这样做,我也想知道。

Let's say I have two classes that look like this:

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

Either class may be instantiated at runtime (via Activator.CreateInstance) to perform a filtering function. The read and write methods will be hooked up at runtime to methods from other classes that will provide and accept byte arrays or packets.

Within each filter is additional code that performs the filtering function:

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

If only one of the above constructor signatures will be present in each filter, how do I determine (using Reflection) which constructor signature is present, so that I can hook up the appropriate methods at runtime?

Note: If I'm daffy and doing this the wrong way, I'd like to know that too.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

柠檬色的秋千 2024-11-20 12:17:23

你不能做一些类似的事情吗?

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

typeof(PacketFilter) 替换为适当的实例。

Can't you do something like?

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

replacing typeof(PacketFilter) with appropriate instance.

莫多说 2024-11-20 12:17:23

没有提到的一个选项是使用 Fasterflect,这是一个为尽可能使反射变得更容易、更快而创建的库。

它还具有一些构建在核心反射功能之上的功能,其中之一是当您不知道哪些构造函数可用时构造对象的能力。

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

还有用于传递命名值字典或离散名称和值数组的重载。最新的代码还提供了扩展,用于仅从有序的值列表构造对象,并按其类型将它们与参数进行匹配。

Fasterflect 将自动选择具有最匹配参数的构造函数。如果无法使用值,它将在构造后尝试设置匹配的属性。您可以选择要求使用所有值。

免责声明:我是该项目的贡献者。

An option that has not been mentioned is to use Fasterflect, a library created to make reflection easier and faster where possible.

It also has a couple of features built on top of the core reflection capabilities, one of which is the ability to construct objects when you don't know what constructors are available.

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

There are also overloads for passing in a dictionary of named values or discrete name and value arrays. The latest code also provides extensions for constructing objects just from an ordered list of values, matching them in order to parameters by their type.

Fasterflect will automatically pick the constructor with the most matching arguments. If it's unable to use a value it'll try to set a matching property after construction. And you have the option of requiring all values to be used.

Disclaimer: I'm a contributor to the project.

来世叙缘 2024-11-20 12:17:23

您可以枚举构造函数(以获取一个构造函数),然后枚举构造函数的参数。由于参数应该是泛型类型,因此您需要枚举每个泛型构造函数参数的泛型类型参数。请注意,所有这些都非常棘手,我建议找到更好的解决方案。反射是一个强大的工具,但使用它会带来复杂性;如果有一个不太复杂的解决方案(例如工厂模式,也许),那会更好。您解决这个特定问题的需求也可能反映了您现有设计的过度复杂性。如果简化原始设计,您可能会发现技术问题就消失了。

You can enumerate the constructors (to get the one constructor) and then enumerate the parameters of the constructor. Since the parameters are expected to be generic types, you then need to enumerate the generic type parameters for each generic constructor parameter. Note that all of this is very hacky and I would recommend finding a better solution. Reflection is a powerful tool and using it introduces complexity; if there is a less complex solution (such as a factory pattern, perhaps), that would be preferable. It's also possible that your need to solve this particular problem reflects excessive complication in your existing design. If you simplify the original design, you may find that the technical problem goes away.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文