Type.GetConstructor (with parameter types) fails for dynamically loaded type - plugins

I have a program that loads plugins using AssemblyLoadContext.LoadFromAssemblyName using this approach.
The plugin assembly loads fine, and I can locate types that implement a required interface, and instantiate these types with their default constructor (using Activator.CreateInstance), but when I try to locate a constructor with a particular parameter type, GetConstructor returns null, even though the required constructor can be seen in the debugger.
When I try the same thing with the same type but statically loaded, the call succeeds.
What is happening here?
Update:
I moved the ILogger parameter out of the constructor into one of the methods that's declared in the interface and now Assembly.GetTypes (via RuntimeModule.GetTypes) throws ReflectionTypeLoadException with "Method 'blah' in type 'blah' from assembly 'blah' does not have an implementation."
The method in question is the one with the ILogger parameter. It's as if the runtime doesn't recognize the ILogger type in the interface and the ILogger type in the runtime-loaded assembly as being the same, but I can't figure out why that should be.
If I remove the ILogger parameter it all works smoothly again.

I was led to an answer by this Nate McMaster article.
Basically the point of the AssemblyLoadContext is to isolate plugins from each other and from the program loading them. Therefore the were not sharing the same ILogger type even though in practice they were using the same version.
So you have to tell the loader not to isolate any libraries that you want to share. You can do this by returning null from the Load method override for the assemblies in question.
internal class PluginLoadContext : AssemblyLoadContext
{
private AssemblyDependencyResolver Resolver { get; }
private string[] SharedAssemblies { get; } =
{
"Microsoft.Extensions.Logging.Abstractions"
};
public PluginLoadContext(string pluginPath)
{
Resolver = new(pluginPath);
}
protected override Assembly? Load(AssemblyName assemblyName)
{
if (SharedAssemblies.Contains(assemblyName.Name))
{
// Use the default resolver
return null;
}
string? assemblyPath = Resolver.ResolveAssemblyToPath(assemblyName);
return assemblyPath != null ? LoadFromAssemblyPath(assemblyPath) : null;
}
protected override IntPtr LoadUnmanagedDll(string unmanagedDllName)
{
string? libraryPath = Resolver.ResolveUnmanagedDllToPath(unmanagedDllName);
return libraryPath != null ? LoadUnmanagedDllFromPath(libraryPath) : IntPtr.Zero;
}
}

Related

Is there a way to have a get only (no set) in a typescript interface?

I have a case where I want to have just a get in the interface, no set. Is there a way to do that?
If not, we can implement a set and throw an exception if it is called. But it's cleaner if we can have just a get.
At present I have:
export interface IElement {
type : TYPE;
}
export class Element implements IElement {
public get type () : TYPE {
return TYPE.UNDEFINED;
}
public set type (type : TYPE) {
this.type = type;
}
}
I would like to have my interface & class be:
export class Element implements IElement {
public get type () : TYPE {
return TYPE.UNDEFINED;
}
}
TypeScript interfaces cannot currently define a property as read-only. If it's important to prevent, you'll need to throw an exception/error at runtime to prevent sets within the setter for the property.
The compiler doesn't require that you implement the get and a set though. You can just implement the get for example. However, at runtime, it won't be caught.

"Signature of the body and declaration in a method implementation do not match"

UPDATE: I think I've eliminated Unity from the equation. See below for more details.
UPDATE 2: I think I may have eliminated Entity Framework fro the equation. See below for more details.
I have some code that is building a unity container, but it started failing with the above error message out of the blue. It works on other people's machines, but not mine. I deleted the folder the solution was in and refreshed everything from source control to ensure I had nothing that could be causing issues (e.g. duplicate assemblies lying around from a previous build).
Here is part of my code:
public static class UnityBootstrapper
{
public static IUnityContainer Initialise()
{
Trace.WriteLine("UnityBootstrapper.Initialise()");
var container = BuildUnityContainer();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
return container;
}
private static IUnityContainer BuildUnityContainer()
{
Trace.WriteLine("UnityBootstrapper.BuildUnityContainer()");
var container = new UnityContainer();
// Other dependencies are registered here
// If the following line is commented out the container is build
// but, obviously, it won't resolve this dependency.
container.RegisterType<IUserAccessEntities, UserAccessEntities>(WebRequestLifetime);
// Other dependencies are registered here
return container;
}
The code apparently fails on the call to BuildUnityContainer(), and I can see that the trace statement I put inside that method is never displayed.
However, if I comment out the line that registers the UserAccessEntities class (which was code generated from Entity Framework 5) then the container is built. Naturally, when I ask for that dependency it can't resolve it, so the code just fails elsewhere.
I've Googled for solutions and they all seem to resolve around generics and moving the generic type from the method to the class level. I can't do that as EF5 creates the class and it puts generics on the properties. e.g
DbSet<MyTable> Tables { get; set; }
The only other thing I can think of is that I've extracted an interface from the EF5 generated class called IUserAccessEntities and the problem could lie there... but I used ReSharper to generate that, so it should be perfectly aligned.
UPDATE
Just to eliminate Unity from the equation, I tried to new up the UserAccessEntities on its own
private static void TestUae()
{
var uae = new UserAccessEntities(); //container.Resolve<IUserAccessEntities>();
Trace.WriteLine("Got the entities: " + uae);
}
And the call to TestUae() fails instead.
UPDATE 2
I created a new class, AlternativeEntities based on the interface I'd previously extracted. When I try to construct that directly it has a new exception: Method 'Set' in type 'AlternativeEntities' from assembly 'UserAccess.Model, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' does not have an implementation.
However, it does. There are two methods called set, both of which I've given a basic implementation:
public class AlternativeEntities : IUserAccessEntities
{
public DbSet<TEntity> Set<TEntity>() where TEntity : class
{
Trace.WriteLine("public DbSet<TEntity> Set<TEntity>() where TEntity : class");
return null;
}
public DbSet Set(Type entityType)
{
Trace.WriteLine("public DbSet Set(Type entityType)");
return null;
}
// Other methods and properties here.
}

Inter Type Declaration on Compiled Class File

Is it possible to do Inter Type Declarations with AspectJ on Compiled Class Files at Load Time Weaving?
As an example: I compile some Groovy code and want to add fields or methods with IDT.
Update:
Oh my goodness, you do not need reflection to access members or execute methods. Eclipse shows errors in the editor, but you may just ignore them, the code compiles and runs fine anyway. So the aspect is really much more strightforward and simple:
public aspect LTWAspect {
public static String Application.staticField = "value of static field";
public String Application.normalField = "value of normal field";
public void Application.myMethod() {
System.out.println(normalField);
}
void around() : execution(void Application.main(..)) {
System.out.println("around before");
proceed();
System.out.println("around after");
System.out.println(Application.staticField);
new Application().myMethod();
}
}
Original answer:
Yes, but you have a hen-and-egg problem there, i.e. you cannot just reference the newly introduced fields from your LTW aspect code without reflection. (The last sentence is not true, see update above.) Plus, in order to make your LTW aspect compile, you need the classes to be woven on the project's build path so as to be able to reference them. Example:
Java project
public class Application {
public static void main(String[] args) {
System.out.println("main");
}
}
AspectJ project
import org.aspectj.lang.SoftException;
public aspect LTWAspect {
public static String Application.staticField = "value of static field";
public String Application.normalField = "value of normal field";
public void Application.myMethod() {
try {
System.out.println(Application.class.getDeclaredField("normalField").get(this));
} catch (Exception e) {
throw new SoftException(e);
}
}
void around() : execution(void Application.main(..)) {
System.out.println("around before");
proceed();
System.out.println("around after");
try {
System.out.println(Application.class.getDeclaredField("staticField").get(null));
Application.class.getDeclaredMethod("myMethod", null).invoke(new Application());
} catch (Exception e) {
throw new SoftException(e);
}
}
}
So, e.g. in Eclipse you need to put the Java project on the AspectJ project's build path under "Projects" because only then it can see Java class Application on which you want to declare members. After compilation you just start the Java project and do LTW on the aspect project (don't forget an aop-ajc.xml referencing LTWAspect).
In my example above I declare a static member, a non-static ("normal") member and a non-static method. My advice prints the static member and calls the non-static method, both via reflection. The non-static method then prints the non-static member, again via reflection. This is not nice, but it works and proves the ITD in combination with LTW is possible. There might be a more elegant way, but if so I am unaware of it. (Update: There is a more elegant way: Just ignore the errors marked by Eclipse IDE, see above.)
Program output
around before
main
around after
value of static field
value of normal field

How to resolve generic type at runtime

I'm trying to build a command processor that can take any command that implements a marker interface (or maybe descends from a base class). The processor will handle the command that it is asked to process. However I'm struggling with resolving the true generic type as Resolve(Type) returns an object.
I'm not sure is how to cast this if at all possible?
public void Process(ICommand command)
{
var c = command.GetType();
var t = typeof(ICommandHandler<>).MakeGenericType(new[] { c });
var o = container.Resolve(t);
//((ICommandHandler)o).Handle(command); *** This doesn't work
}
The calling code would be something like this -
Dispatcher.Process(new SomeCommand(Guid.NewGuid(),"Param1",12345));
If you absolutely have to call the ICommandHandler<T>.Handle method and you have no other control over the design of the system, then reflection may be your only choice. There's no great way to deal with the switch from generic to non-generic.
Otherwise, you may have a couple of options.
First, if your Dispatcher.Process can be made generic, you can save all the casting.
public static class Dispatcher
{
public static void Process<T>(T command) where T : ICommand
{
var handler = container.Resolve<ICommandHandler<T>>();
handler.Handle(command);
}
}
This is a pretty common solution to a problem like this that I've seen out in the wild.
If you can't do that, then you may be able to make your ICommandHandler<T> interface implement a non-generic ICommandHandler base interface.
public interface ICommandHandler
{
void Handle(ICommand command);
}
public interface ICommandHandler<T> : ICommandHandler
{
void Handle(T command);
}
In this latter case you'd have to switch your strongly-typed command handler implementations to call the same internal logic for generic or basic handling or you'll get different handling based on the call, which would be bad:
public class SomeCommandHandler : ICommandHandler<SomeCommand>
{
public void Handle(ICommand command)
{
var castCommand = command as SomeCommand;
if(castCommand == null)
{
throw new NotSupportedException("Wrong command type.");
}
// Hand off to the strongly-typed version.
this.Handle(castCommand);
}
public void Handle(SomeCommand command)
{
// Here's the actual handling logic.
}
}
Then when you resolve the strongly-typed ICommandHandler<T> your cast down to ICommandHandler (as shown in your question's sample code) will work.
This is also a pretty common solution, but I've seen it more in systems that existed before generics were available where an updated API was being added.
However, in all cases here, the problem really isn't that Autofac is returning an object; it's a class/type design problem that affects any generic-to-non-generic conversion scenario.
Using Reflection - but is this the best way to approach this?
public void Process(Command command)
{
var c = command.GetType();
var ot = typeof(ICommandHandler<>);
var type = ot.MakeGenericType(new[] { c });
var mi = type.GetMethod("Handle");
var o = container.Resolve(type);
mi.Invoke(o, new object[] { command });
}

Reflection / C# typing errors when publishing an F# class implementing an interface

I have an interface written in C#, but when implementing it in F#, I noticed some oddities.
The F# class has to be cast to the interface before C# can consume it
After casting, WPF can't read it's properties (Bindings failed and SNOOP was unable to reflect on it)
I can wrap the object in C# code and everything works fine.
the interface
public interface IInterpret {
public string Name {get;}
public IEnumberable<Project> Interpret(string text);
}
The F# Class
type Interpreter()=
interface IInterpret with
member x.Name = "FParsec Based"
member x.Interpret(str) = Seq.empty
The code below fails to compile
The error is about Interpreter not implementing IInterpert
public ViewModel(){
IInterpret i = new FSharpLib.Interperter();
}
This is my current workaround
public class MyProxy: IInterpret{
private IInterpret _cover;
public MyProxy() {
_cover = new FSharpLib.Interperter() as IInterpret;
}
public string Name { get { return _cover.Name; } }
public IEnumerable<Project> Interpret(string text){
return _cover.Interpret(text);
}
}
Is there something I'm doing wrong with my F# class def, or is the proxy needed? I'm using the current VS2010 f#, not an out of band drop.
F# implements all interfaces explicitly. This means you must explicitly cast to the interface type.
I don't know a ton about WPF binding to explicit interfaces, but see if these
http://leecampbell.blogspot.com/2008/09/generic-binding-in-wpf-through-explicit.html
http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/92a2a3ba-74a6-4c79-9c75-f42d232a4dbf
help? (I just found them Bing-ing for "wpf binding explicit interfaces".)
(Another alternative may be to do something like
type Interpreter()=
member x.Name = "FParsec Based"
member x.Interpret(str:string) = Seq.empty
interface IInterpret with
member x.Name = x.Name
member x.Interpret(str) = x.Interpret(str)
where you "explicitly implement the interface implicitly", if you pardon the confusing terminology.)