ChangeTracking icon indicating copy to clipboard operation
ChangeTracking copied to clipboard

Proxy Creation fails for Non-Virtual readonly properties???

Open CorsairRO opened this issue 4 years ago • 7 comments

Hello,

I started to look at your library because it looks exactly what I will need to enable change tracking in my app. My app uses .NET Framework 4.7.2 and is a WPF+SQL Server+EntityFramework app

Now, first I got an error about not all my DataObject properties being virtual. OK, I made them virtual.

The problem is my ListProperties are ObservableCollection<T>, and not IList<T> Now I got an error saying property Count is not virtual? In ObservableCollection => property Count DOES NOT HAVE A SETTER, only a getter. Not to mention that I cannot edit it to be virtual even if I wanted to, as it belongs to Microsoft.

The error comes when I do trackable.AcceptChanges() and it has a property of type ObservableCollection<MyChildDataRow>

Now, my questions would be:

  1. Can I ignore ALL properties defined in the BaseClass of my DataObject and use ONLY properties defined in the DataObject class.
  2. Can I NOT get an exception for a Non-Virtual property? I don't care that it will not participate in the change tracking, I just want to be able to use the library

Related to 1) Is there any way by default to Exclude everything from hierarchy and let me to manually mark things that I want to? Similar to Json.OptIn functionality.

Thank you very much for your help.

FullStackTrace of the error ( cutting out my Main static method from my test console app ) My Object is called wc_package

at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor) at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) at System.Reflection.RuntimePropertyInfo.GetValue(Object obj, BindingFlags invokeAttr, Binder binder, Object[] index, CultureInfo culture) at System.Reflection.RuntimePropertyInfo.GetValue(Object obj, Object[] index) at ChangeTracking.ComplexPropertyInterceptor1.MakeAllPropertiesTrackable(Object proxy) in C:\projects\changetracking\Source\ChangeTracking\ComplexPropertyInterceptor.cs:line 176 at ChangeTracking.ComplexPropertyInterceptor1.ComplexPropertyTrackables(Object proxy) in C:\projects\changetracking\Source\ChangeTracking\ComplexPropertyInterceptor.cs:line 165 at ChangeTracking.ComplexPropertyInterceptor1.Intercept(IInvocation invocation) in C:\projects\changetracking\Source\ChangeTracking\ComplexPropertyInterceptor.cs:line 144 at Castle.DynamicProxy.AbstractInvocation.Proceed() at ChangeTracking.EditableObjectInterceptor1.Intercept(IInvocation invocation) in C:\projects\changetracking\Source\ChangeTracking\EditableObjectInterceptor.cs:line 87 at Castle.DynamicProxy.AbstractInvocation.Proceed() at ChangeTracking.ChangeTrackingInterceptor1.Intercept(IInvocation invocation) in C:\projects\changetracking\Source\ChangeTracking\ChangeTrackingInterceptor.cs:line 96 at Castle.DynamicProxy.AbstractInvocation.Proceed() at ChangeTracking.NotifyPropertyChangedInterceptor1.Intercept(IInvocation invocation) in C:\projects\changetracking\Source\ChangeTracking\NotifyPropertyChangedInterceptor.cs:line 68 at Castle.DynamicProxy.AbstractInvocation.Proceed() at Castle.Proxies.wc_packageProxy.get_ComplexPropertyTrackables() at ChangeTracking.Internal.Utils.GetChildren[TResult](Object proxy, List1 parents) in C:\projects\changetracking\Source\ChangeTracking\Internal\Utils.cs:line 12 at ChangeTracking.ChangeTrackingInterceptor1.AcceptChanges(Object proxy, List1 parents) in C:\projects\changetracking\Source\ChangeTracking\ChangeTrackingInterceptor.cs:line 300 at ChangeTracking.ChangeTrackingInterceptor1.Intercept(IInvocation invocation) in C:\projects\changetracking\Source\ChangeTracking\ChangeTrackingInterceptor.cs:line 148 at Castle.DynamicProxy.AbstractInvocation.Proceed() at ChangeTracking.NotifyPropertyChangedInterceptor`1.Intercept(IInvocation invocation) in C:\projects\changetracking\Source\ChangeTracking\NotifyPropertyChangedInterceptor.cs:line 83 at Castle.DynamicProxy.AbstractInvocation.Proceed() at Castle.Proxies.wc_packageProxy.AcceptChanges()

CorsairRO avatar Feb 27 '20 16:02 CorsairRO

Hi @CorsairRO

Can you please provide a small sample describing your problem?

Thanks.

joelweiss avatar Feb 28 '20 21:02 joelweiss

Hello,

as I said, I just have an object with some scalar properties, and a property of type ObservableCollection<T>, let's say my object is an Order, and the ObservableCollection are the Order Items.

The ObservableCollection has a ReadOnly property for Count, only with a get. The Property is NOT virtual and it cannot be as ObservableCollection is a type defined in Microsoft namespaces.

If I exclude complex properties from the changetracking, my object works fine, but I would also like to track changes of child lists.

thank you for your quick answer there... have a nice day

CorsairRO avatar Mar 02 '20 06:03 CorsairRO

This appears to be a bug, For now you have 2 options Use IList<T>,

public virtual IList<OrderDetail> OrderDetails { get; set; }

Or add [DoNoTrack]

[DoNoTrack]
public virtual ObservableCollection<OrderDetail> OrderDetails { get; set; }

joelweiss avatar Mar 02 '20 08:03 joelweiss

Hello,

Ok, thank you very much for your reply.

Is there any problem if I make a copy of your library and change it to adapt my needs there?

Like by default disabling change tracking on all properties of an object. And me manually mark them with some attribute that they participate into change tracking? Exclude all non-virtual properties by default, and not throw any exception, just in debug mode.

I will post an example to your github project after I have done it.

Thank you, Have a nice day

Thank you / Tak / Multumesc

Cosmin Palade Senior Developer Phone: +40 744 535 995 Email: [email protected]mailto:[email protected] Skype: cosmin.palade Teams: [email protected]mailto:[email protected] Web: http://www.lundin.rohttp://www.lundin.ro/

From: Joel Weiss [email protected] Sent: Monday, March 2, 2020 10:43 To: joelweiss/ChangeTracking [email protected] Cc: Cosmin Palade [email protected]; Mention [email protected] Subject: Re: [joelweiss/ChangeTracking] Proxy Creation fails for Non-Virtual readonly properties??? (#66)

This appears to be a bug, For now you have 2 options Use IList<T>,

public virtual IList<OrderDetail> OrderDetails { get; set; }

Or add [DoNoTrack]

[DoNoTrack]

public virtual ObservableCollection<OrderDetail> OrderDetails { get; set; }

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHubhttps://github.com/joelweiss/ChangeTracking/issues/66?email_source=notifications&email_token=AJPH7YXPQX3E7THGXRFC5H3RFNWTDA5CNFSM4K46DMH2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOENONKJI#issuecomment-593286437, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AJPH7YRJTJK4AHBPSCGZXQLRFNWTDANCNFSM4K46DMHQ.

CorsairRO avatar Mar 02 '20 15:03 CorsairRO

Sure thing, Licence permits it.

joelweiss avatar Mar 04 '20 08:03 joelweiss

BTW from README

By default complex properties and collection properties will be tracked (if it can be made trackable).

You can change the default by setting

ChangeTrackingFactory.Default.MakeCollectionPropertiesTrackable = false;

ChangeTrackingFactory.Default.MakeComplexPropertiesTrackable = false;

joelweiss avatar Mar 04 '20 20:03 joelweiss

Hehe, yes, I’ve seen that, thank you.

Thing is I want to make it work in a somehow different manner similar to Json OptIn functionality.

And definitively I want the child collections to be in the schema.

Meaning that I want to decide which properties contribute to the ChangeTracking, like for example my Domain Object Properties, like OrderNr, OrderDate , ObservableCollection<OrderItem >and so on. I am using a Customized T4 to generate them from EF, and I can mark all of these with some custom attribute to indicate that they should participate in.

Rest of properties from the class, like my custom business logic fields like readonly properties (calculated) IsOrderSent and so on, I will NOT add them there. Also my Base Class properties that doesn’t have anything to do with the state of Object, like IsLoaded, IsInitialized, and so on.

Thank you, Have a nice day there

Thank you / Tak / Multumesc

Cosmin Palade Senior Developer Phone: +40 744 535 995 Email: [email protected]mailto:[email protected] Skype: cosmin.palade Teams: [email protected]mailto:[email protected] Web: http://www.lundin.rohttp://www.lundin.ro/

From: Joel Weiss [email protected] Sent: Wednesday, March 4, 2020 22:15 To: joelweiss/ChangeTracking [email protected] Cc: Cosmin Palade [email protected]; Mention [email protected] Subject: Re: [joelweiss/ChangeTracking] Proxy Creation fails for Non-Virtual readonly properties??? (#66)

BTW from READMEhttps://github.com/joelweiss/ChangeTracking/blob/master/README.md

By default complex properties and collection properties will be tracked (if it can be made trackable).

You can change the default by setting

ChangeTrackingFactory.Default.MakeCollectionPropertiesTrackable = false;

ChangeTrackingFactory.Default.MakeComplexPropertiesTrackable = false;

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHubhttps://github.com/joelweiss/ChangeTracking/issues/66?email_source=notifications&email_token=AJPH7YW5UCPHNJOSOMSPON3RF2ZEBA5CNFSM4K46DMH2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEN2BSCI#issuecomment-594811145, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AJPH7YWKWTUWPYX5CXGXFGTRF2ZEBANCNFSM4K46DMHQ.

CorsairRO avatar Mar 05 '20 06:03 CorsairRO