jsgoupil/quickbooks-sync

StepQueryResponseBase should not constrain to new()

mscappini opened this issue · 1 comments

I've hit a small wall in my implementation. I now have a step that can return 1 of 2 request types, based on runtime results. But given the generic arguments of StepQueryResponseBase, I can only provide one type to be serialized for the request and one type to be deserialized for the response, and those types must be a class and must have a parameterless constructor.

I believe we can resolve this by not constraining to new() on StepQueryResponseBase. This way, the generic type can simply be a contract. I would then be able to, for example, make a wrapper class that implements both QbRequest and QbResponse, and then run logic based on the type of the returned response. Or I could just return a QbRequest when creating the request, and the serializer will still serialize properly. The onus would then be on the imeplementer to cast the returned response appropriately.

Then we could also make StepQueryResponseBase.CreateRequest either abstract to allow the implementer to return whatever is required for that call, or keep it virtual and try to invoke a parameterless constructor via reflection to get an instance of T (then maybe wrap/throw if an exception is thrown).

protected virtual T CreateRequest(AuthenticatedTicket authenticatedTicket)
{
    System.Type tType = typeof(T);

    ConstructorInfo ctor = tType.GetConstructor(System.Type.EmptyTypes);
    if (ctor == null)
        throw new MissingMethodException(tType.Name, tType.Name);

    return (T)ctor.Invoke(null);
}

The only hangup I see with the reflection approach (opposed to the abstract approach) is that I don't believe we are using reflection anywhere else in the project, and reflection can require higher permissions if the assembly is loaded with restricted permissions in a locked down environment (like a GoDaddy shared host or something).

I will close this. I went with a different approach, instead of allowing you to implement a class for both the QbRequest and QbResponse, I prefer to put them separate for a better understanding.
If this is still an issue, we can revisit.