Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inheritance of Attributes from Interface Members #593

Closed
bepursuant opened this issue Jul 14, 2021 · 3 comments
Closed

Inheritance of Attributes from Interface Members #593

bepursuant opened this issue Jul 14, 2021 · 3 comments

Comments

@bepursuant
Copy link

Hello team - This might be an easy one to put to rest, I think I just need a castle expert to look at it.

I have an issue with a separate project, and I think it comes down to something in the Castle proxy generation.

The root of the question is - can Castle allow my generated proxy to inherit attributes from its source Interface? The linked issue has an example project demonstrating the disconnect.

@stakx
Copy link
Member

stakx commented Jul 14, 2021

Hi @bepursuant. I don't remember all the implementation details without looking them up, but off the top of my head:

As a rule of thumb, DynamicProxy only replicates non-inherited custom attributes. There is currently no mechanism or option to change that behavior. The only thing you can do is globally specify (via AttributesToAvoidReplicating) custom attribute types that should not get replicated... but that is the exact opposite of what you need.

DescriptionAttributes will not get replicated because they are inherited. Let's check its definition:

[AttributeUsage(AttributeTargets.All)]
public class DescriptionAttribute : Attribute

Its [AttributeUsage] does not explicitly specify Inherited = false, so the default (Inherited = true) applies.

Knowing this, you could try subclassing DescriptionAttribute and then reapply [AttributeUsage] with Inherited = false. If you then use that custom attribute type, DynamicProxy should replicate it on the generated proxy type.

Let's try this:

using System;
using System.ComponentModel;
using System.Reflection;

using Castle.DynamicProxy;

var generator = new ProxyGenerator();

var foo = generator.CreateInterfaceProxyWithoutTarget<IFoo>();
var fooAttr = foo.GetType().GetProperty("Property").GetCustomAttribute<DescriptionAttribute>();
Console.WriteLine(fooAttr?.Description);  // => no output because attribute is not there

var bar = generator.CreateInterfaceProxyWithoutTarget<IBar>();
var barAttr = bar.GetType().GetProperty("Property").GetCustomAttribute<DescriptionAttribute>();
Console.WriteLine(barAttr?.Description);  // => outputs "Some description"

public interface IFoo
{
    [Description("Some description")]
    object Property { get; set; }
}

public interface IBar
{
    [NonInheritedDescription("Some description")]
    object Property { get; set; }
}

[AttributeUsage(AttributeTargets.All, Inherited = false)]
public class NonInheritedDescriptionAttribute : DescriptionAttribute
{
    public NonInheritedDescriptionAttribute(string description) : base(description) { }
}

Not sure if this will help in your situation, but it may be worth a shot.

@stakx
Copy link
Member

stakx commented Aug 15, 2021

@bepursuant: has the above post answered your question? (If so, let's close this issue.)

@bepursuant
Copy link
Author

@stakx - thanks so much for the thorough explanation and example resolution. This exactly solved my dilemma, with only three lines of code! Really appreciate the help! I've added the details to my original issue in the aloneguid/config project for anyone else looking at a similar issue.

shoaibshakeel381 pushed a commit to shoaibshakeel381/Castle.Core that referenced this issue Sep 17, 2022
- This is complementary to AttributesToAvoidReplicating
- This will allow consumers to specify attributes which should always be
  copied to generated proxy. It is especially useful where we do not own
  target interfeces and/or cannot override attributes, e.g. attributes
  used by various frameworks. This was mentioned in castleproject#593
- Similar effect could by achieved in Castle.Core Version 4.4.1 by simply extending various generator classes but in 5.0 all those classes were marked internal, without this fix we now have to override half the library, So this fix offers an alternative path.
- Fixes castleproject#607
shoaibshakeel381 pushed a commit to shoaibshakeel381/Castle.Core that referenced this issue Mar 6, 2023
- This is complementary to AttributesToAvoidReplicating
- This will allow consumers to specify attributes which should always be
  copied to generated proxy. It is especially useful where we do not own
  target interfeces and/or cannot override attributes, e.g. attributes
  used by various frameworks. This was mentioned in castleproject#593
- Similar effect could by achieved in Castle.Core Version 4.4.1 by simply extending various generator classes but in 5.0 all those classes were marked internal, without this fix we now have to override half the library, So this fix offers an alternative path.
- Fixes castleproject#607
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

No branches or pull requests

2 participants