{"action":"created","issue":{"url":"https://api.github.com/repos/dotnet/corefx/issues/34791","repository_url":"https://api.github.com/repos/dotnet/corefx","labels_url":"https://api.github.com/repos/dotnet/corefx/issues/34791/labels{/name}","comments_url":"https://api.github.com/repos/dotnet/corefx/issues/34791/comments","events_url":"https://api.github.com/repos/dotnet/corefx/issues/34791/events","html_url":"https://github.com/dotnet/corefx/issues/34791","id":402475731,"node_id":"MDU6SXNzdWU0MDI0NzU3MzE=","number":34791,"title":"AssemblyLoadContext .NET Core 3.0 improvements","user":{"login":"sdmaclea","id":25674984,"node_id":"MDQ6VXNlcjI1Njc0OTg0","avatar_url":"https://avatars3.githubusercontent.com/u/25674984?v=4","gravatar_id":"","url":"https://api.github.com/users/sdmaclea","html_url":"https://github.com/sdmaclea","followers_url":"https://api.github.com/users/sdmaclea/followers","following_url":"https://api.github.com/users/sdmaclea/following{/other_user}","gists_url":"https://api.github.com/users/sdmaclea/gists{/gist_id}","starred_url":"https://api.github.com/users/sdmaclea/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sdmaclea/subscriptions","organizations_url":"https://api.github.com/users/sdmaclea/orgs","repos_url":"https://api.github.com/users/sdmaclea/repos","events_url":"https://api.github.com/users/sdmaclea/events{/privacy}","received_events_url":"https://api.github.com/users/sdmaclea/received_events","type":"User","site_admin":false},"labels":[{"id":165998434,"node_id":"MDU6TGFiZWwxNjU5OTg0MzQ=","url":"https://api.github.com/repos/dotnet/corefx/labels/api-ready-for-review","name":"api-ready-for-review","color":"5319e7","default":false},{"id":174276033,"node_id":"MDU6TGFiZWwxNzQyNzYwMzM=","url":"https://api.github.com/repos/dotnet/corefx/labels/area-System.Runtime","name":"area-System.Runtime","color":"d4c5f9","default":false}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":{"url":"https://api.github.com/repos/dotnet/corefx/milestones/21","html_url":"https://github.com/dotnet/corefx/milestone/21","labels_url":"https://api.github.com/repos/dotnet/corefx/milestones/21/labels","id":3242632,"node_id":"MDk6TWlsZXN0b25lMzI0MjYzMg==","number":21,"title":"3.0","description":".NET Core 3.0, next major release after 2.1. See [official release dates](https://github.com/dotnet/core/blob/master/roadmap.md) for details.\r\n\r\nWe will move important issues from Future to 3.0 as the priorities and dates for next release become more clear.","creator":{"login":"karelz","id":5776068,"node_id":"MDQ6VXNlcjU3NzYwNjg=","avatar_url":"https://avatars2.githubusercontent.com/u/5776068?v=4","gravatar_id":"","url":"https://api.github.com/users/karelz","html_url":"https://github.com/karelz","followers_url":"https://api.github.com/users/karelz/followers","following_url":"https://api.github.com/users/karelz/following{/other_user}","gists_url":"https://api.github.com/users/karelz/gists{/gist_id}","starred_url":"https://api.github.com/users/karelz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/karelz/subscriptions","organizations_url":"https://api.github.com/users/karelz/orgs","repos_url":"https://api.github.com/users/karelz/repos","events_url":"https://api.github.com/users/karelz/events{/privacy}","received_events_url":"https://api.github.com/users/karelz/received_events","type":"User","site_admin":false},"open_issues":433,"closed_issues":5376,"state":"open","created_at":"2018-04-04T16:40:10Z","updated_at":"2019-03-20T19:07:52Z","due_on":null,"closed_at":null},"comments":58,"created_at":"2019-01-23T23:28:42Z","updated_at":"2019-03-20T19:34:56Z","closed_at":null,"author_association":"MEMBER","body":"## Motivations\r\n### Concrete Type\r\nThere is a desire to simplify `System.Runtime.Loader.AssemblyLoadContext` usage by making it a concrete type.  (from #34535)\r\n\r\nThe existing class is abstract because the `Load()` method is not implemented.  Recommend adding a default implementation of `Load()` as a method returning `null` and make the constructors public. This is a logical default implementation as it implies falling back to the `AssemblyLoadContext.Default` for first chance to load the assembly.\r\n\r\n### Naming ALCs\r\nTo simplify diagnostics for `System.Runtime.Loader.AssemblyLoadContext` (from #34530):\r\n * Add a `Name` to each ALC making understanding of role of each ALC easier\r\n\r\nThe name will make it more convenient to understand what is happening in the debugger.  It will also make any tracing easier to understand.\r\n\r\n+ The Default ALC would be constructed with name = \"Default\".\r\n+ The Assembly.LoadFile(path) generated ALCs would be constructed with name =  \"Assembly.LoadFile(_path_)\" .\r\n+ Custom AssemblyLoadContext implementations could provide a logical name.  \r\n+ The legacy Custom AssemblyLoadContext using the current protected constructor will not set the name.  In these cases the name will default to `null`.\r\n\r\n### Set of ALCs & Assemblies\r\nProvide a mechanism to iterate through ALCs and their contents to create a graphical representation. These APIs are intended to help make understanding and diagnosing isolation designs (from #34530). \r\n\r\nAdd `Contexts`, and `Assemblies` properties.\r\n\r\n### ActiveForContextSensitiveReflection\r\n\r\nThere is a need for a general solution to allow code executing outside a given `AssemblyLoadContext` to behave as if it was loaded within the context for a small set of context sensitive reflection APIs. These APIs are used to load assemblies and resolve types by name.  Their behavior is currently sensitive to their caller's `AssemblyLoadContext`.\r\n\r\nThis is required in part because of the design of `AssemblyLoadContext` which:\r\n* Requires `System.Private.CoreLib` to be loaded exclusively in the `Default` context. \r\n* Strongly recommends the runtime framework be completely loaded into the `Default` context.\r\n* Recommends most frameworks be loaded exclusively in the `Default` context.\r\n\r\nThis means code executing on behalf of an `AssemblyLoadContext` is not loaded into its client `AssemblyLoadContext`.  This means the existing mechanism for inferring the currect `AssemblyLoadContext` is insufficient in some scenarios. The typical case is when a framework or library is using reflection on behalf of client code loaded into a custom `AssemblyLoadContext`\r\n\r\nThis proposal is for a mechanism for code to explicitly set a specific `AssemblyLoadContext` as the `ActiveForContextSensitiveReflection` for a using block and its asynchronous flow of control.  Previous context is restored upon exiting the using block. Blocks can be nested.\r\n\r\n#### Context Sensitive Reflection APIs\r\nThe following is an exhaustive set of APIs which will be affected, by `AssemblyLoadContext.ActiveForContextSensitiveReflection`.  \r\n\r\n(The set is exhaustive as of preview 3, but may grow as we fix dotnet/coreclr#22213)\r\n```C#\r\nnamespace System\r\n{\r\n    public static partial class Activator\r\n    {\r\n        public static ObjectHandle CreateInstance(string assemblyName, string typeName);\r\n        public static ObjectHandle CreateInstance(string assemblyName, string typeName, bool ignoreCase, BindingFlags bindingAttr, Binder binder, object[] args, CultureInfo culture, object[] activationAttributes);\r\n        public static ObjectHandle CreateInstance(string assemblyName, string typeName, object[] activationAttributes);\r\n    }\r\n    public abstract partial class Type : MemberInfo, IReflect\r\n    {\r\n        public static Type GetType(string typeName, bool throwOnError, bool ignoreCase);\r\n        public static Type GetType(string typeName, bool throwOnError);\r\n        public static Type GetType(string typeName);\r\n        public static Type GetType(string typeName, Func<AssemblyName, Assembly> assemblyResolver, Func<Assembly, string, bool, Type> typeResolver);\r\n        public static Type GetType(string typeName, Func<AssemblyName, Assembly> assemblyResolver, Func<Assembly, string, bool, Type> typeResolver, bool throwOnError);\r\n        public static Type GetType(string typeName, Func<AssemblyName, Assembly> assemblyResolver, Func<Assembly, string, bool, Type> typeResolver, bool throwOnError, bool ignoreCase);\r\n    }\r\n}\r\nnamespace System.Reflection\r\n{\r\n    public abstract partial class Assembly : ICustomAttributeProvider, ISerializable\r\n    {\r\n        public static Assembly Load(string assemblyString);\r\n        public static Assembly Load(AssemblyName assemblyRef);\r\n    }\r\n}\r\n```\r\n#### Basic Usage\r\n```C#\r\n  AssemblyLoadContext alc = new AssemblyLoadContext();\r\n  using (alc.ActivateForContextSensitiveReflection())\r\n  {\r\n    // In this block, alc acts as the current executing context for context sensitive reflection APIs.\r\n    //\r\n    // This does not mean all assemblies will be loaded into it. Nor does it mean the set of type\r\n    // resolved by it will come exclusively from assemblies it has loaded.\r\n    // \r\n    // Rather when alc is ActiveForContextSensitiveReflection, the context sensitive reflection APIs\r\n    // behavior will be modified such that:\r\n    //\r\n    // When loading assemblies, alc.Load() is called first, before falling back to default. \r\n    // alc.Resolve(...) handler will be called before AppDomain.ResolvingAssembly(...)\r\n    //\r\n    // When resolving types, the type cache in this alc is consulted. It will include types \r\n    // loaded into other AssemblyLoadContexts but used by this context\r\n    \r\n    Assembly assembly = Assembly.Load(myPlugin); // Attempts to loads calling alc.Load() first, with normal fallback.\r\n    \r\n    Type t = GetType(\"MyPlugin.MyType\"); // Resolves type as if alc was active execution context\r\n\r\n    // Affects async methods\r\n    TResult result = await AsyncMethod();\r\n\r\n    // Ideally also affects threads and queued work items.\r\n    Thread t = new Thread(new ThreadStart(ThreadProc));\r\n    t.Start();\r\n\r\n    ThreadPool.QueueUserWorkItem(ThreadProc);\r\n  }\r\n```\r\n#### Maintaining and restoring original behavior\r\n```C#\r\nstatic void Main(string[] args)\r\n{\r\n  // On App startup, AssemblyLoadContext.ActiveContext is null\r\n  // Behavior prior to .NET Core 3.0 is unchanged\r\n  Assembly assembly = Assembly.Load(myPlugin); // Will load into the Default ALC.\r\n}\r\n\r\nvoid SomeMethod()\r\n{\r\n  using (AssemblyLoadContext.ActivateForContextSensitiveReflection(null))\r\n  {\r\n    // AssemblyLoadContext.ActiveContext is null\r\n    // Behavior prior to .NET Core 3.0 is unchanged\r\n    Assembly assembly = Assembly.Load(myPlugin); // Will load into the ALC containing SomeMethod(). \r\n  }\r\n}\r\n```\r\n#### Design doc\r\nDetailed design doc is in review dotnet/coreclr#23335.\r\n\r\n## Proposed API changes\r\n\r\n```C#\r\n// Add a public constructor\r\n// Allow naming each AssemblyLoadContext\r\npublic AssemblyLoadContext(String name, bool isCollectible = false);\r\n\r\n// Add default Load() implementation\r\nprotected virtual System.Reflection.Assembly Load(System.Reflection.AssemblyName assemblyName)\r\n{\r\n    return null;\r\n}\r\n  \r\npublic String Name { get; }\r\n  \r\n// Override the ToString to return Name, type name, and unique instance id.\r\npublic override string ToString();\r\n\r\n// Set of ALCs\r\npublic static IEnumerable<AssemblyLoadContext> Contexts { get; }\r\n\r\n// Set of Assemblies in the ALC\r\npublic IEnumerable<System.Reflection.Assembly> Assemblies { get; }\r\n\r\n// When set supersedes implicit context as determine by callers assembly for the limited set of \r\n// context reflection APIs.  \r\n// Implemented as AsyncLocal<AssemblyLoadContext> to allow setting to follow async & threads\r\npublic static AssemblyLoadContext ActiveForContextSensitiveReflection { get { return _asyncLocalActiveContext.Value; }}\r\n\r\n// Allow client to explicitly set the active context for a using block\r\npublic IDisposable ActivateForContextSensitiveReflection();\r\n\r\n// Convenience method to call AssemblyLoadContext on an assemblies parent\r\n// Activate(null) will explicitly clear the ActiveContext until the IDisposable.Dispose()\r\nstatic public IDisposable Activate(Assembly activating);\r\n```\r\n## Open issues\r\n* `ActiveForContextSensitiveReflection` design still settling\r\n* Consider renaming `Contexts` to `AllContexts` or `GetAllContexts`\r\n\r\n"},"comment":{"url":"https://api.github.com/repos/dotnet/corefx/issues/comments/474996275","html_url":"https://github.com/dotnet/corefx/issues/34791#issuecomment-474996275","issue_url":"https://api.github.com/repos/dotnet/corefx/issues/34791","id":474996275,"node_id":"MDEyOklzc3VlQ29tbWVudDQ3NDk5NjI3NQ==","user":{"login":"swaroop-sridhar","id":8977622,"node_id":"MDQ6VXNlcjg5Nzc2MjI=","avatar_url":"https://avatars1.githubusercontent.com/u/8977622?v=4","gravatar_id":"","url":"https://api.github.com/users/swaroop-sridhar","html_url":"https://github.com/swaroop-sridhar","followers_url":"https://api.github.com/users/swaroop-sridhar/followers","following_url":"https://api.github.com/users/swaroop-sridhar/following{/other_user}","gists_url":"https://api.github.com/users/swaroop-sridhar/gists{/gist_id}","starred_url":"https://api.github.com/users/swaroop-sridhar/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/swaroop-sridhar/subscriptions","organizations_url":"https://api.github.com/users/swaroop-sridhar/orgs","repos_url":"https://api.github.com/users/swaroop-sridhar/repos","events_url":"https://api.github.com/users/swaroop-sridhar/events{/privacy}","received_events_url":"https://api.github.com/users/swaroop-sridhar/received_events","type":"User","site_admin":false},"created_at":"2019-03-20T19:34:56Z","updated_at":"2019-03-20T19:34:56Z","author_association":"CONTRIBUTOR","body":">> ActivateForContextSensitiveReflection\r\n\r\n👍 Thanks @sdmaclea; this definitely helps clarify the semantics of the API."}}
{"actor":{"display_login":"swaroop-sridhar"}}