-
Notifications
You must be signed in to change notification settings - Fork 47
Conversation
… in starting with the JsonPatchDocument
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good! A couple of suggestions, though.
public class AdapterFactory : IAdapterFactory | ||
{ | ||
/// <inheritdoc /> | ||
public virtual IAdapter Create(object target, IContractResolver contractResolver) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about just passing in the JsonContract
since that's all the contractResolver
will be used for in this context?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Either way. The JsonContract
must match the target type passed in. Since the code doesn't already have a JsonContract
we can trust the developer to properly create it and pass it in, or just create it in the function. The original ObjectVisitor.SelectAdapter
method generated the JsonContract
in the method, so I followed the same approach. We can create it in the ObjectVisitor.SelectAdapter
but if somebody tries to use an AdapterFactory
outside the current scope they have to do it correctly. This seemed less error prone to me, but if you would prefer it the other way, it is an easy change. Let me know.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I prefer passing in JsonContract
instead of contractResolver
. I'm assuming AdapterFactory
won't be used in an unforeseen way. This way the JsonContract
will be gotten once instead of by every IAdapterFactory
implementation, which seems less error-prone to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think it can reuse the JsonContract
because that is specific to the target for that given SelectAdapter
call. For example, if you look at ObjectVisitor.TryVisit' you will see that we are passing in a different target as we traverse the path. That results in a different 'JsonContract' each time. So we aren't getting any performance gains of reuse. Ultimately it comes down to putting that line of code in 'ObjectVisitor.SelectAdapter' or in 'AdapterFactory.Create'. If it goes into
SelectAdapter` we are potentially limiting a future extension of the 'AdapterFactory' by only providing the 'JsonContract'. Am I missing something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My words "gotten once" were poorly chosen. I meant to suggest that the line of code for getting the JsonContract
be in only one place in the library (ObjectVisitor.SelectAdapter
), instead of in every IAdapterFactory
implementation. My idea is to keep AdapterFactory.Create
tightly scoped to it's intended purpose. Maybe you have a potential scenario in mind that I haven't considered?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just wondering how people might try and use the AdapterFactory for other purposes and having that code embedded gives them more control and makes it less likely for somebody to pass in the wrong JsonContract. I think it comes down to 6 or a half dozen, so I can go ahead and make the change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see the difference of where we're coming from. You're arguing against redundancy of the data passed to Create
. I'm arguing against redundancy of the code that generates that data. I think I found a compromise that addresses both concerns, and leads to a better API too. I posted my new suggestion on your updated code.
/// <param name="target">The target object</param> | ||
/// <param name="contractResolver">The current contract resolver</param> | ||
/// <returns>The needed <see cref="IAdapter"/></returns> | ||
IAdapter Create(object target, IContractResolver contractResolver); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest a JsonContract
instead of a contractResolver
.
/// <summary> | ||
/// Gets or sets the <see cref="IAdapterFactory"/> | ||
/// </summary> | ||
public IAdapterFactory AdapterFactory { get; set; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about making this readonly (removing setter)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just preference I guess. I like to have my properties externally set able in case it makes unit testing easier. That being said we don't currently need it, so if you would prefer it to be read only, I can do that. Again, just let me know it is an easy fix. Thanks for the quick feedback.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yea, I'd prefer that it's read-only. This makes it consistent with the other constructor parameters contractResolver
and logErrorAction
. Constructor-set properties are generally read-only in my experience.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As for "Add support for inheritance of built in adapters", they're straight-forward changes. Yea, this could be useful in some extension scenarios.
- Changed ObjectAdapter.AdapterFactory to readonly - Changed IAdapterFactory.Create to provide the JsonContract instead of the ContractResolver.
@HappyNomad, Updated made based on feedback. Thanks! |
@@ -13,20 +13,18 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters | |||
public class AdapterFactory : IAdapterFactory | |||
{ | |||
/// <inheritdoc /> | |||
public virtual IAdapter Create(object target, IContractResolver contractResolver) | |||
public virtual IAdapter Create(object target, JsonContract targetContract) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Our discussion got me thinking: here I am arguing about contractResolver
vs. jsonContract
but none of my extension scenarios require either (I just use target is
and an object type). So now I have a different suggestion. Let's pass IAdapterFactory.Create
neither contractResolver
nor jsonContract
. Create
's target
parameter already contains all the information that method needs. As you pointed out, we shouldn't preclude anyone from using a contractResolver
. But we're not! For AdapterFactory
for example, its constructor can accept contractResolver
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You do bring up a good point, although that doesn't really follow the pattern established within the library and it would be possible to have a disconnect between the ContractResolver being used within the AdapterFactory and the rest of the library. I would vote to leave it as is, or go back to passing in the ContractResolver to Create. Nothing says that parameter needs to be used within the AdapterFactory.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure what you mean by "doesn't really follow the pattern established within the library and it would be possible to have a disconnect between the ContractResolver being used within the AdapterFactory and the rest of the library". ObjectVisitor
stores a reference to _contractResolver
, and perhaps that's the case elsewhere in the library, too.
This new suggestion actually follows the same pattern that my app will use with IAdapterFactory
. That is, extra data that the factory needs will be passed into the factory's constructor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I simply mean that all the downstream classes (ObjectAdapter, ObjectVisitor, etc.) use the same ContractResolver that was initially passed into the JsonPatchDocument. Having the AdapterFactory get its own instance out of that flow could cause a disconnect. If the AdapterFactory has its own instance, then you could pass in a different ContractResolver to the JsonPatchDocument (and the classes it creates) than the one that the AdapterFactory is using. I haven't through through the impacts of using a different resolver in the multiple areas. This could certainly be an issue where the developer needs to do it "right" it just seems like we could insulate them a little bit from accidentally doing something wrong. To your point, one could still pass in anything they want to a custom AdapterFactory, really we are arguing about the default implementation which the code should be able to make work however we want.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still don't follow. JsonPatchDocument.ApplyTo
passes its top-level contract resolver to ObjectAdapter
's constructor, which passes the same to ObjectVisitor
's constructor, which would pass the same to AdapterFactory
's constructor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't want to go the internal route. I am actually overriding the base AdapterFactory in my implementation so I want to be able to instantiate it. Let's pass the ContractResolver into the AdapterFactory as a constructor parameter. The source code is available for a reason if somebody wants to know what is going on. This still doesn't introduce any breaking changes and does keep things flexible. I will work on that update tomorrow am and let you know when its ready for a review. It shouldn't take long to make the change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good, thanks. BTW, you could mark it as protected internal
in that case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now that I understand you want to derive from AdapterFactory
and pass your subclass into JsonPatchDocument
's constructor, I see how the AdapterFactory
constructor requiring a contractResolver
would be slightly inconvenient. You'd have to first instantiate DefaultContractResolver
to pass to both your factory subclass's constructor and JsonPatchDocument
's constructor. Like you said, this also raises the possibility that two different contract resolvers could get involved. In light of this, I defer to you on this one. Take any of the routes we discussed, including passing contractResolver
or JsonContract
into IAdapterFactory.Create
if you decide that's best.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I am going to rollback to passing the contractResolver in IAdapterFactory.Create as I think it provides a good balance in flexibility while allowing the creation of the AdapterFactory to remain simple. I will let you know when the code as been pushed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updates made. I think we should be good to go.
…m to a different branch that can be tracked locally.
@Eilon @HappyNomad, Thanks, |
@jmudavid Wish I could help, but I just don't know. Let us know if you figure it out. |
@jmudavid Although we want to minimize code additions, I find the following usage too verbose:
Not only must I include the boilerplate What do you think about adding a
|
@Eilon, On a side note, once we get his finished, and we finalize the changes in the PR, what are the next steps for considering the change? |
@HappyNomad, Adding new constructors is an easy fix, but we have to draw the line someplace. At this point I want to get his PR fixed and closed, then additional refinement can be made once the main functionality is available. |
@mkArtakMSFT can someone on your team evaluate this proposal and maybe also take a look at the test issues? |
@jmudavid Have you tried configuring deserialization to pass
And then you can deserialize with the settings:
This verbosity is necessary since we decided to have
And then replace the |
There's also a simpler way to deserialize and pass in
|
@HappyNomad, In my scenario I actually use a custom version of the JsonPatchDocument to support SCIM, so my custom object was able to set the IAdapterFactory rather than relying on serialization. Based on your second comment, it looks like you have a way of moving forward, but maybe not. I see what you are saying about the JsonPatchDocumentConverter. I will need to play around with it a little to make sure I properly understand how it is leveraged so I can test it properly. |
…ion by making the Converters support inheritance. Added support for both JsonPatchDocument and the typed version. Cleaned up some minor code smells from before.
@HappyNomad, Ok both Converters have been updated so they can be overridden. I added a test to cover this scenario as well. |
@jmudavid Looks good. For deserializing and passing in |
@jmudavid Now I'm working on deserialization on the server. As for calling the
A custom input formatter is also excluded as an option for the second and third reasons. The easiest approach is for my controller action to accept a Seeing our decision to pass |
@HappyNomad, |
@mkArtakMSFT, |
@jmudavid Yea, setting the I don't think that storing the adapter factory at
I relate to your desire to build in the correct (for each of our scenarios) |
@HappyNomad At this point I want to minimize the changes needed to complete this PR until we can get it merged and out of a branch. I believe we have a working solution for both scenarios even though it could still be further refined. |
Thanks @mkArtakMSFT, we appreciate it. Note that as I explained in dotnet/aspnetcore#2432 and dotnet/aspnetcore#2743,
Regarding point 1, by using the proposed
The spec doesn't mention .NET's Regarding point 2, |
/// </summary> | ||
/// <param name="operations">The operations to assign to the JsonPatchDocument</param> | ||
/// <returns>A new instance of the JsonPatchDocument</returns> | ||
protected virtual JsonPatchDocument CreateContainer(List<Operation> operations ) => |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not totally sure what this is here for - how do you expect this to be used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@rynowak We added this purely for extension purposes. If I remember correctly @HappyNomad needed a custom JsonPatchDocumentConverter, and breaking out this portion to be overridden allowed the rest of the ReadJson function to be used rather than being duplicated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, what are the scenarios for a custom converter? What problems are being solved?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking back through the thread, @HappyNomad needed to provide his custom adapter factory as part of the deserialization process. I didn't need to for my scenario, and to be honest I never went back to understand why one of us needed it and the other didn't.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@HappyNomad - care to reply?
I don't think this is blocking if we don't get a response. I just like to know what's going on 😆
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, what are the scenarios for a custom converter? What problems are being solved?
For an answer, see #132 (comment) .
But as long as I can pass IAdapterFactory
to ApplyTo
, I won't need it. See #132 (comment) .
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggested this while thoroughly considering @jmudavid's suggestion to pass IAdapterFactory
to JsonPatchDocument
's constructor. He was suggesting customization via the constructor, so in a deserialization scenario I may want to access that customization ability and this would allow me to do it.
As you can see from my other comments today, I believe @jmudavid's deviation from the existing API is a mistake. Not only that, but I discovered the arguments I'd need to pass to JsonPatchDocument
's constructor aren't available until ApplyTo
-time anyway. So from my perspective, in the same way that the changes proposed for JsonPatchDocument
are unnecessary (and even harmful), I believe the changes here can be rolled back as well.
protected virtual object CreateTypedContainer(Type objectType, object operations) | ||
{ | ||
return Activator.CreateInstance(objectType, operations, new DefaultContractResolver()); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, not totally sure what this is going to be used for... it would be good to talk through the scenarios.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above. Just trying to allow custom Converters to be created with as little code duplication as possible.
[JsonIgnore] | ||
public IAdapterFactory AdapterFactory { get; set; } | ||
|
||
public JsonPatchDocument():this(new List<Operation>(), new DefaultContractResolver()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Formatting, please put the : this
... and everything after on a separate line (3-4 cases of this in the PR)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please exclude changes to this file, for the reasons I mentioned earlier.
{ | ||
return new PocoAdapter(); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be good to see some unit tests for this method now that it's an abstraction rather than a detail.
/// <inheritdoc /> | ||
public virtual IAdapter Create(object target, IContractResolver contractResolver) | ||
{ | ||
var jsonContract = contractResolver.ResolveContract(target.GetType()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add argument checking - what should the behavior be when the target
is null? IIRC that should be an exception.
/// <summary> | ||
/// The default AdapterFactory to be used for resolving <see cref="IAdapter"/>. | ||
/// </summary> | ||
public class AdapterFactory : IAdapterFactory |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it make sense for the AdapterFactory
to wrap the IContractResolver
? IE, you can provide an adapter factory or a contract resolver:
- if you customized the contract resolver but not the adapter factory then we create the default adapter factory
- if you customized the adapter factory then you're expect to figure out how you want to handle contracts
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@rynowak, I see how this would simplify the code by having a single element to pass around, although it seems to me like we would be asking one class to handle two different purposes. Did you have another goal in mind for consolidating these?
Late in the PR, @HappyNomad suggested we moved the AdpaterFactory to the ApplyTo, rather than being part of the Constructor. We had different philosophical views on why, but a decision there might impact a decision here. In addition to understanding the goal behind your suggestion, I wanted to also get your thoughts on that aspect. Ultimately if we can get this rolled into production it would be great, so I don't mind a little additional refactoring if it will help us move this forward, I just would rather not do it too many more times ;)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was asking to try and reason about whether or not they are the came concern. The current adapter factory implementation is only thing in the system that interacts with contracts current (I think).
If we were implementing this system fresh (without JSON.NET) we would put the details about how to traverse different types on our equivalent of JsonContract
.
I don't have any major concerns or strong feedback about what you and @HappyNomad have been discussing, I think both proposals are pretty reasonable. We don't have the luxury of designing something new here because it has to fit into the existing APIs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The concrete implementations of IAdapter are what actually use the ContractResolver. The AdapterFactory only uses it to pass through. You are right that we probably could pull it into the AdapterFactory, but it would create more complexity to keep the interface backwards compatible. It looks like (quick review) that the ContractResolver can be added in various ways (constructor, converter, ApplyTo, etc) so we would need to handle the old mechanism and the new mechanism in all these locations. I agree that building it fresh it probably makes sense to have the AdpaterFactory provided it if needed. I am willing to refactor if that will help us get this merged, otherwise I am inclined to make fewer changes than are needed to meet the primary goal of this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok great, I'm convinced.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Late in the PR, @HappyNomad suggested we moved the AdpaterFactory to the ApplyTo, rather than being part of the Constructor.
I suggested that from the beginning, although I did thoroughly consider your idea to instead accept it in JsonPatchDocument
's constructor. I concluded to stand by my original idea to only accept it in ApplyTo
. I summarized my reasoning at dotnet/aspnetcore#2816 (comment) and we discussed it starting at #132 (comment) .
IAdapterFactory
is a means of customizing ObjectAdapter
which is a means of customizing JsonPatchDocument
. The existing design is to pass ObjectAdapter
to ApplyTo
. You want to allow the customization of ObjectAdapter
(IAdapterFactory
) to be passed to JsonPatchDocument
's constructor while ObjectAdapter
is still passed to ApplyTo
? IMHO that's making things more messy and for no good reason.
Please delegate the idea to bake custom behavior into a JsonPatchDocument
instance to a separate issue rather than conflating it here. In that separate issue, I think you should consider a JsonPatchDocument
constructor that accepts the more general IObjectAdapter
instead of the more specific IAdapterFactory
.
Please keep this pull request focused and don't touch JsonPatchDocument
or JsonPatchDocument<T>
. Both of our scenarios will work fine without touching those classes. The extraneous changes you suggest are unnecessary for fulfilling both of our needs. They may also benefit from further consideration in a separate issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't have the luxury of designing something new here because it has to fit into the existing APIs.
That's exactly my point. IObjectAdapter
is already being passed to ApplyTo
, so let's not pretend we can undo that design decision by passing IAdapterFactory
to JsonPatchDocument
's constructor. Instead, let's be consistent with the existing API and leave JsonPatchDocument
alone.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this looks overall great. Thanks for bearing with us, I know we've put this off for a long time.
@rynowak Glad you can look at this now. I think most of your questions can be answered by reading comments on the issue and pull request. Sorry, I don't have time to look at all of it again right now. |
} | ||
} | ||
|
||
public class TestAdapter : IAdapter |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If these are top-level classes, they should each have their own file
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jmudavid - I think this is just about ready to go, but there are a few minor things to resolve:
- top-level classes should have their own files (in tests)
- add tests for
AdapterFactory
- fix formatting of
public JsonPatchDocument():this
- add argument validation to new public/protected methods
If you can't find time to get to these some time in the next few days then I'll do it and merge after.
@rynowak, I hadn't started on the remaining items since I didn't disagree with your feedback but wanted to make sure we got the other areas worked out. I will try and get these updates made this week, although things are a little busy around here. |
} | ||
|
||
// Create from list of operations | ||
public JsonPatchDocument(List<Operation<TModel>> operations, IContractResolver contractResolver) | ||
public JsonPatchDocument(List<Operation<TModel>> operations, IContractResolver contractResolver, IAdapterFactory adapterFactory) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please exclude changes to this file, for the reasons I mentioned earlier.
public ObjectAdapter( | ||
IContractResolver contractResolver, | ||
Action<JsonPatchError> logErrorAction) | ||
Action<JsonPatchError> logErrorAction, | ||
IAdapterFactory adapterFactory) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is all we need - no need to modify JsonPatchDocument
.
Guys, even more important than the clean up you're discussing, is to talk about why those extraneous changes are being made to |
@jmudavid You're deriving from |
@HappyNomad, I know you want to pass in the factory at the ApplyTo method, and unless I am mistaken, you can do that in the current code. You may be right that all we need is the ApplyTo, however I don't see the problem with being able to provide it in the Constructor, so the user doesn't have to create a custom ObjectAdapter. I don't believe that the current approach is contrary to the existing design as the ContractResolver can also be applied globally or directly to the ObjectAdapter. None of the changes made trigger a breaking change to the API, so I don't see the harm in allowing the Adapter to be set at either location depending on the users need. If @rynowak feels this change should be made, then so be it, he is the gatekeeper. |
The problem is that the "it" in your sentence is the specific |
An AdapterFactory implementation is not required in the JsonPatchDocument constructor. So, in your scenario, the default would be applied, but the one provided in the custom ObjectAdapter would be used. Unnecessary, possibly, but in the scenario that I have where I can set it once and reuse apply, it makes the API easier to use. I am not using a custom ObjectAdapter (now that the factory is there). |
I don't have major concerns with any of the suggestions being discussed here. I also don't feel like I don't know 100% of every problem that's being solved beyond "we want to extend the adapter factory" - but I also haven't been a participant in the discussion. But that's OK, I'm here to try and make sure you both will be happy with the outcome once we complete this work. We could go one of two ways to resolve this:
If you need an absolute tiebreaker, I'd always lean towards the change that exposes the least new surface area 😆 |
This sounds similar to what I advocated in this context since I wrote dotnet/aspnetcore#2816 (comment). I said:
I don't have much more to say about it. |
As I understand it, the current solution works well for both of us, even if it provides some capabilities that we both don't need. While I agree that minimizing the changes is ideal, I don't think there is a good reason not to give developers more flexibility one how to extend and use the API. That being said, I am willing to perform the clean up tasks requested so we can get this merged so I don't have to maintain a fork. I am sure we all have other priorities we need to get to so continuing the philosophical debate over this isn't a wise use of anybodies time. If @HappyNomad feels strongly enough in his approach, I would suggest he create a new fork, he can cherry pick the changes he needs, and can submit a new PR and we can just close this one out. |
Than can you just undo the changes that you don't need?
Let me explain my point of view... My goal is to limit the extensibility and flexibility of the API to set of reasonable scenarios that work well and we can maintain and support over a period of years. I don't want extras without a clear purpose attached to them. I'd be really happy to help you, @HappyNomad or anyone else in the future accomplish reasonable things that are withing the scope of this project - but this always comes with understanding what those requirements are as a first step. |
@rynowak, First off, thank you for taking some time to look at this PR with us. Trying to get this changes integrated has taken multiple months, so I am sorry if some frustration in the process is showing. I would rather not make additional changes, simply because the code has been refactored multiple times (many as a result of feedback from @HappyNomad that I agreed with and provided a better, easier API). I don't see the current implementation increasing surface area or making it more difficult to maintain. All that being said, I (as I am sure we all do) have many balls in the air and getting this mainlined is more valuable to me than having it my way. So rather than continuing to argue about what I feel is a very minor implementation detail, I will just make the change so that we can get it mainlined rather than having this drag on for another few months. I will close this PR when the update is ready so that we can have a cleaner commit history. |
@rynowak, I now remember the other reason I don't want to make code changes. I can't get the JsonPatch tests to run on my machine anymore. I was trying to troubleshoot this previously dotnet/aspnetcore#2946 and never got anyplace. My errors have progressed to the new SDK:
I can compile both projects fine, I just can't run any tests. I have tried the troubleshooting from the original issue, but it is attempting (and failing) to load an older version of the SDK (Using KoreBuild 2.2.0-preview1-17051). I pulled a fresh copy of the repo from https://github.com/aspnet/JsonPatch.git and I get the same thing. I have updated VS 2017 to the latest preview, and no luck. I can only assume something is messed up within my environment, but reinstalling everything isn't really an good option right now, so unless I know where to look/clean I am not sure what to do. Do you have any advice/suggestions? Thanks. |
do a Some more details: https://github.com/aspnet/Home/wiki/Building-from-source |
Thank you for that link. It looks like I may not be able to use the Test Explorer at this point, and need to use the build.cmd file, is that right? (It at least appears that way on my machine.) That is fine if that is the case, but I know I was using the test explorer previously, so maybe there was a change made along the way, entirely possible. If using the build.cmd is the right way to test, I will go that way. Thanks! |
Yeah, something wierd is going on with test explorer. I'm not sure exactly what is the problem, most folks here are focused on the 2.1 RTM which is why it hasn't gotten any attention yet. |
@rynowak @HappyNomad, New PR available for your review which passes directly to the ObjectAdapter. I will close this PR. |
@HappyNomad, @Eilon, Here is the new PR with the initial factory model implementation for your review. Let me know what you think, Thanks!