MarcinJuraszek / CloneExtensions

Clone extension method library. Performs fast, deep or shallow clone using simple assignment operations generated by Expression Tree runtime code compilation.
Apache License 2.0
115 stars 30 forks source link

Cloning of objects where runtime type is not declared type #7

Open sdfreyder opened 8 years ago

sdfreyder commented 8 years ago

When cloning objects whose runtime time differs from the declared type (as would be the case with a derived type using polymorphism) the resulting object is of the declared (less-derived) type instead of the runtime (derived) type.

The attached zip contains a short test program which demonstrates the issue.

clonetest.zip

MarcinJuraszek commented 7 years ago

Yes, that's a known limitation. Doing a runtime type check on every cloned object would make the entire cloning process quite slow. I think it would be worth adding as an opt-in functionality though (an extra Boolean flag on GetClone method.

I might get on that soon, but if you feel like you'd be able to contribute that change I'm happy to accept a Pull Request.

sdfreyder commented 7 years ago

I think we got the cloning of the runtime-defined type to work but ultimately the problem that stopped us was the fact that the expression-tree-generated code wasn't able to assign to private members/fields.

MarcinJuraszek commented 7 years ago

I can see how that might be a problem. I think it should still be possible to use CloneExtensions to copy the public members using a custom initializer logic provided in initialize dictionary. I'll add something to the documentation when I have a moment later today.

sdfreyder commented 7 years ago

Oh yes - that works very nicely.  We got the cloning to work fine with public members and using (as I recall) Activator.CreateInstance (and therefore not requiring the dictionary), but for our use-case, it turned out that not being able to clone the the private members was a complete show-stopper.  I seems clear that private members can be copied using either Reflection, or Reflection.Emit-generated code, but not by Expression-trees, I don't know why.

deipax commented 7 years ago

You can set private members using Expressions but you need to use the FieldInfo or PropertyInfo fetched from the class via reflection. Particularly, these overloads:

public static MemberExpression Field(Expression expression, FieldInfo field); public static MemberExpression Property(Expression expression, PropertyInfo property)

sdfreyder commented 7 years ago
Next
    time I get some spare cycles I shall look into that - thanks for
    the info Marcin.

On 8/13/2017 9:00 AM, deipax wrote:

  You can set private members using Expressions but you need to
    use the FieldInfo or PropertyInfo fetched from the class via
    reflection. Particularly, these overloads:
  public static MemberExpression Field(Expression expression,
    FieldInfo field);
    public static MemberExpression Property(Expression expression,
    PropertyInfo property)
  —
    You are receiving this because you authored the thread.
    Reply to this email directly, view
      it on GitHub, or mute
      the thread.

  {"api_version":"1.0","publisher":{"api_key":"05dde50f1d1a384dd78767c55493e4bb","name":"GitHub"},"entity":{"external_key":"github/MarcinJuraszek/CloneExtensions","title":"MarcinJuraszek/CloneExtensions","subtitle":"GitHub repository","main_image_url":<a class="moz-txt-link-rfc2396E" href="https://cloud.githubusercontent.com/assets/143418/17495839/a5054eac-5d88-11e6-95fc-7290892c7bb5.png">"https://cloud.githubusercontent.com/assets/143418/17495839/a5054eac-5d88-11e6-95fc-7290892c7bb5.png"</a>,"avatar_image_url":<a class="moz-txt-link-rfc2396E" href="https://cloud.githubusercontent.com/assets/143418/15842166/7c72db34-2c0b-11e6-9aed-b52498112777.png">"https://cloud.githubusercontent.com/assets/143418/15842166/7c72db34-2c0b-11e6-9aed-b52498112777.png"</a>,"action":{"name":"Open in GitHub","url":<a class="moz-txt-link-rfc2396E" href="https://github.com/MarcinJuraszek/CloneExtensions">"https://github.com/MarcinJuraszek/C

loneExt ensions"}},"updates":{"snippets":[{"icon":"PERSON","message":"@deipax in #7: You can set private members using Expressions but you need to use the FieldInfo or PropertyInfo fetched from the class via reflection. Particularly, these overloads:\r\n\r\npublic static MemberExpression Field(Expression expression, FieldInfo field);\r\npublic static MemberExpression Property(Expression expression, PropertyInfo property)\r\n"}],"action":{"name":"View Issue","url":"https://github.com/MarcinJuraszek/CloneExtensions/issues/7#issuecomment-322043937"}}}

rafaelbenavent commented 4 years ago

Cloning of objects where runtime type is not declared type does not seem to work if the declared type is an abstract or interface type. Fails with error "You have to provide initialization expression for "