Skip to content

Conversation

@stakx
Copy link
Member

@stakx stakx commented Jan 31, 2021

During proxy type generation, collected events, methods, and properties are stored at three distinct levels:

  1. in a MetaType model (which is shared by all involved contributors)
  2. in each contributor (i.e. subclasses of CompositeTypeContributor)
  3. in each member collector (i.e. subclasses of MembersCollector)

It turns out that member collectors don't need to hold on to the members they're collecting; their members are only ever queried in order to be transferred into MetaType and the owning contributor.

This PR refactors existing code such that member collectors can directly send the collected members to where they need to end up. By doing so, we can avoid unnecessary collection allocations and element copying.

@stakx stakx force-pushed the dp/refactor/members-collector branch from d84e9cd to 333c665 Compare January 31, 2021 23:23
stakx added 8 commits February 1, 2021 00:55
`TypeElementCollection` contains logic for preventing type element name
collisions by means of switching to explicit implementation.

`CompositeTypeContributor` doesn't just add collected type elements to
its own collections; it first adds them to a `MetaType`, which uses
`TypeElementCollection` internally.

Because of this, nothing is gained by using `TypeElementCollection` in
`CompositeTypeContributor`, too, as one can switch to explicit implemen-
tation only once per method.
`checkedMethods` already ensures the same method cannot be added twice.
Using dictionaries for `events`, `methods`, and `properties` in theory
prevents duplicates when processing the same `MemberInfo` twice. The
code paths leading up to the `Add` methods (plus `checkedMethods`) how-
ever already guarantee once-only execution per `MemberInfo`. Because
the dictionary keys aren't needed we can use a simpler collection type.
`CollectElementsToProxyInternal` acts both as a command (it invokes type
element collectors) and as a query (it returns those collectors, too).
This is not ideal.

Turn this method into a query (`GetCollectors`). The collectors must be
invoked by the caller. This reveals that there is only a single caller:
`CompositeTypeContributor`.
Many of `MembersCollector`'s methods have a `hook` parameter so that it
can be forwarded to the three `Add` methods. This wouldn't be necessary
if it were available e.g. via a field.

Simply assigning `hook` to a field in `CollectMembersToProxy` is not
ideal because it worsens the temporal dependency: intermediate methods
now require that `CollectMembersToProxy` be called beforehand.

Assigning `hook` to a field in the constructor would be better, but all
sub-class ctors and their callers would have to be refactored, too.

Turning the `Add` methods (plus intermediates) into local functions of
`CollectMembersToProxy` solves this problem neatly: they gain access to
the `hook` parameter, and the temporal problem evaporates since those
dependent methods can now be called only inside `CollectMembersToProxy`.
A previous commit revealed that `CompositeTypeContributor` is the sole
direct user of `MembersCollector`. It queries the latter's type element
collections (`Events`, `Methods`, and `Properties`) only to transfer
the elements somewhere else.

This means that `MembersCollector` doesn't really need its own collect-
ions; it could simply send collected type elements to wherever they need
to go. This is done via the new interface `IMembersCollectorSink`.

In principle, this also turns `CollectMembersToProxy` into a repeatable
operation: `checkedMethods` no longer needs to act double duty as a flag
to check whether the method was already called.
@stakx stakx force-pushed the dp/refactor/members-collector branch from 333c665 to 9902dc2 Compare January 31, 2021 23:55
@stakx stakx merged commit de1a3c4 into castleproject:master Feb 3, 2021
@stakx stakx deleted the dp/refactor/members-collector branch February 3, 2021 17:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants