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 eac开发者_开发百科h 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.
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.
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.
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.
精彩评论