Hello SO;
I'm planning to ask a fairly elaborate question that is also something of a musing here, so bear with me...
I'm trying to design a factory implementation for a simulation application. The simulation will consist of different sorts of entities i.e. it is not a homogenous simulation in any respect. As a result, there will be numerous very different concrete implementations and only the very general properties will be abstracted at the top level.
What I'd like to be able to do is create new simulation entities by calling a method on the model with a series of named arguments representing the parameters of the entity, and have the model infer what type of object is being described by the inbound parameters (from the names of the parameters and potentially the sequence they occur in) and call a factory method on the appropriate derived class.
For example, if I pass the model a pair of parameters (Param1=5000, Param2="Bacon") I would like it to infer that the names Param1 and Param2 'belong' to the class "Blob1" and call a shared function "getBlob1" with named parameters Param1:=5000, Param2:="Bacon" whereas if I pass the model (Param1=5000, Param3=50) it would call a similar factory method for Blob2; because Param1 and Param3 in that order 'belong' to Blob2.
I foresee several issues to resolve:
- Whether or not I can reflect on the available types with string parameter names and how to do this if it's possible
- Whether or not there's a neat way of doing the appropriate constructor inference from the combinatoric properties of the argument list or whether I'm going to have to bodge something to do it 'by hand'.
- If possible I'd like the model class to be able to accept parameters as parameters rather than as some collection of keys and values, which would require the model to expose a large number of parametrised methods at runtime without me having to code them explicitly - presumably one for every factory method available in the relevant namespace.
What I'm really asking is how you'd go about implementing such a system, rather than whether or not it's fundamentally possible. I don't have the foresight or experience with .NET reflection to be able to figure out a way by myself. Hopefully this will prove an informative discussion.
UPDATE:
Well, I've had a crack at implementing a simple case, a toy model, essentially. The core logic is thus:
Dim members() As Reflection.MethodInfo = Me.GetType.GetMethods()
Dim params_enum As IEnumerator(Of String) = params.Keys.GetEnumerator
While params_enum.MoveNext
members = Array.FindAll(members, _
Function(m As Reflection.MethodInfo) Array.Exists(CType(m, Reflection.MethodInfo).GetParameters(), _
Function(mm As Reflection.ParameterInfo) mm.Name = params_enum.Current))
If members.Count = 0 Then Return False
End While
Try
CType(members(0), Reflection.MethodInfo).Invoke(Me, params.Values.ToArray())
Return True
Catch ex As Exception
Return False
End Try
This just picks a method on the current instance and executes it. I'd like to extend that to a subset of all the types in the assembly. I'd also like to do this, if possible, by letting those types decide what their parametrised initialisation requirements are at runtime by examining their own properties, i.e. each property marked with 'ParametrisedInitAttribute' corresponds to exactly one named argument in the factory method. This would require that I have these types expose a method with N arguments at runtime. Is there a way to construct a method with an arbitrary signature and add it to the class implementation at runtime, or a similar way of doing this sort of thing?