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

Should DynamicProxy emit IgnoresAccessChecksToAttribute? #402

Closed
stakx opened this issue Jul 20, 2018 · 7 comments
Closed

Should DynamicProxy emit IgnoresAccessChecksToAttribute? #402

stakx opened this issue Jul 20, 2018 · 7 comments

Comments

@stakx
Copy link
Member

stakx commented Jul 20, 2018

Yesterday, I was made aware of the small wonder that is [assembly: IgnoresAccessChecksTo("AssemblyName")]. This attribute might be useful for DynamicProxy.

What is it?

Put simply, this attribute type is the reverse of InternalsVisibleToAttribute. It can be applied in a dynamic assembly to get access to the internal members of another assembly. It is supported by the .NET Core 1.0+ and the .NET Framework 4.6+ runtimes. The BCL does not pre-define that attribute type, one has to define it e.g. inside the dynamic assembly as follows:

namespace System.Runtime.CompilerServices
{
    [AttributeUsageAttribute(AttributeTargets.Assembly, AllowMultiple = true)]
    public class IgnoresAccessChecksToAttribute : Attribute
    {
        private string _assemblyName;
        public IgnoresAccessChecksToAttribute(string assemblyName)
        {
            _assemblyName = assemblyName;
        }
        public string AssemblyName 
        { 
            get { return _assemblyName; } 
        } 
    }
}

There isn't a lot of information about this attribute (it appears to be undocumented, unfortunately but perhaps for understandable reasons), here's a few links if you want to learn more:

What would this be good for?

If DynamicProxy automatically emitted that attribute type definition in its dynamic modules, and (recursively) applied it for the assemblies containing proxied types, downstream users running on recent framework versions would no longer need the [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] bit.

For people running on an older platform (.NET Framework <4.6), there would be no change from DynamicProxy's current behavior.

Is it a good idea to always have access to internal members?

That's the one thing I am not sure about. Are there cases where users do not want DynamicProxy to see / intercept / be able to proxy internal types or type members? Would there have to be some kind of configuration switch that allows people to opt in/out of DynamicProxy automatically emitting [IgnoresAccessChecksTo]?

/cc @blairconrad, @dtchepak, @thomaslevesque, @zvirja

@stakx stakx changed the title Should DynamicProxy emit [assembly: IgnoresAccessChecksTo("...")] attributes? Should DynamicProxy emit IgnoresAccessChecksToAttribute? Jul 20, 2018
@thomaslevesque
Copy link
Contributor

Interesting, thanks @stakx for mentioning this.

If DynamicProxy automatically emitted that attribute type definition in its dynamic modules, and (recursively) applied it for the assemblies containing proxied types

I foresee a problem with this. DynamicProxy doesn't know in advance for which types a proxy will be requested. But assembly level attributes have to be defined at assembly creation, right? I assume it's not possible to add attributes after the assembly has been created?

@stakx
Copy link
Member Author

stakx commented Jul 21, 2018

@thomaslevesque:

But assembly level attributes have to be defined at assembly creation, right? I assume it's not possible to add attributes after the assembly has been created?

I think that's not a problem. I've quickly tried this in my Gist (link above) by moving the assembly-level attribute application towards the end of the Gist, after all other types have been baked. That worked just fine. I believe it is only the C# language that requires [assembly: ...] to precede any other code.

@AArnott
Copy link

AArnott commented Jul 21, 2018

There is indeed a requirement. Once the CLR has loaded any type from the assembly, the magic attribute can't be added later or it will have no effect. So all the attributes have to be added at once up front or else you have to create a new dynamic assembly.

@AArnott
Copy link

AArnott commented Jul 21, 2018

See microsoft/vs-mef#93 for a relevent bug fix regarding when the magic attributes are applied.

@stakx
Copy link
Member Author

stakx commented Jul 21, 2018

@AArnott: Thanks for that bit of information. Small follow-up question: That PR you've linked to takes care not to generate more dynamic assemblies than necessary. Do you know how problematic / inefficient it would be for the runtime (both CLR, and CoreCLR) if one generated a new dynamic assembly for each proxy type? That is, if the runtime had to deal with potentially hundreds of small dynamic modules in memory?

In either case, @thomaslevesque is probably right and we cannot use this attribute for DynamicProxy as long as we share one dynamic assembly for many proxy types (as opposed to one dynamic assembly per proxy type). Which is how things are probably going to stay for the foreseeable future.

I guess we can close this then.

@AArnott
Copy link

AArnott commented Jul 21, 2018

I don't know the exact cost. But there is a perfect and memory cost for each assembly that the CLR loads. Which is why we tried to avoid it.

@stakx
Copy link
Member Author

stakx commented Jul 21, 2018

@AArnott - I might run a few benchmarks to learn more about the exact cost someday, but for now my curiosity is satisfied. Makes sense to keep the number of loaded assemblies low. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants