Answered by:
casting a dynamically loaded class to an interface

Question
-
Okay, new day, new heap of questions
Here's my code
Assembly assembly = Assembly.LoadFile(file); Type type = assembly.GetType("AbstractionLayer.IDataProvider"); IDataProvider instance = Activator.CreateInstance(type) as IDataProvider; dataproviderlist.Add(instance);
and I'm getting the error "cannot create an object of type 'interface'"
The thing is, though, I don't want to implement an object of type 'interface'. I want to implement an object of a type which implements this interface.Saturday, January 16, 2010 5:24 PM
Answers
-
Loosely speaking, your code would be equivalent to something like this:
IDataProvider instance = new AbstractionLayer.IDataProvider();
i.e. you are asking the CLR to create an instance of an interface and this is impossible as the error message states.
This is not some arbitrary limitation... there could be several unrelated types that implement the interface, so the CLR has no way to know which concrete type it should create.
If you know that the assembly contains some type that implements the desired interface, but you don't know its name, you could just filter that out:
Assembly assembly = Assembly.LoadFile (file);
Type [] types = assembly.GetTypes ();
Type firstCompatibleType = types.FirstOrDefault (t => t.GetInterfaces ().Contains (typeof (IDataProvider)));
if (firstCompatibleType != null) {
IDataProvider instance = Activator.CreateInstance (firstCompatibleType) as IDataProvider;
}
HTH
--mc- Marked as answer by Bin-ze Zhao Wednesday, January 20, 2010 3:11 AM
Saturday, January 16, 2010 5:57 PM -
From your previous post I'm guessing that a factory pattern would help you out. There are many kinds of factories, but in it's simplest form it is an object from which you request interfaces.
What you're creating is often referred to as a "plug-in", so I'm going to use that term.
The following code shows one way to implement a factory pattern. The reason for having a separate factory object is that your main application can be ignorant of the concrete types in the plug-in dll that implement various interfaces. It only has to be aware of the interfaces and the existance of a single concrete type (the factory).
// Shared interface definition file namespace Environment { public interface IFactory { object GetInterface(Type interfaceType); } public interface ISomeInterface { } } // Plug-in DLL namespace Environment { public class Factory : IFactory { public object GetInterface(Type interfaceType) { if (interfaceType == typeof(ISomeInterface)) return new SomeObject(); // else if (...) return null; } } public class SomeObject : ISomeInterface { } } // Application that makes use of Plug-in DLL namespace SomeApp { // Handy helper class public static class PlugInFactory { private static Environment.IFactory factory; public static object GetInterface(Type interfaceType) { if (factory == null) factory = (Environment.IFactory)Activator.CreateInstanceFrom("MyPlugIn.dll", "Environment.Factory"); return factory.GetInterface(interfaceType); } } public static class Program { static void Main() { // Anywhere in your program you can get a new instance of an // object that implements a specific interface Environment.ISomeInterface instance = (Environment.ISomeInterface)PlugInFactory.GetInterface(typeof(Environment.ISomeInterface)); } } }
- Proposed as answer by Louis.fr Monday, January 18, 2010 9:31 AM
- Marked as answer by Bin-ze Zhao Wednesday, January 20, 2010 3:11 AM
Saturday, January 16, 2010 7:23 PM
All replies
-
Loosely speaking, your code would be equivalent to something like this:
IDataProvider instance = new AbstractionLayer.IDataProvider();
i.e. you are asking the CLR to create an instance of an interface and this is impossible as the error message states.
This is not some arbitrary limitation... there could be several unrelated types that implement the interface, so the CLR has no way to know which concrete type it should create.
If you know that the assembly contains some type that implements the desired interface, but you don't know its name, you could just filter that out:
Assembly assembly = Assembly.LoadFile (file);
Type [] types = assembly.GetTypes ();
Type firstCompatibleType = types.FirstOrDefault (t => t.GetInterfaces ().Contains (typeof (IDataProvider)));
if (firstCompatibleType != null) {
IDataProvider instance = Activator.CreateInstance (firstCompatibleType) as IDataProvider;
}
HTH
--mc- Marked as answer by Bin-ze Zhao Wednesday, January 20, 2010 3:11 AM
Saturday, January 16, 2010 5:57 PM -
From your previous post I'm guessing that a factory pattern would help you out. There are many kinds of factories, but in it's simplest form it is an object from which you request interfaces.
What you're creating is often referred to as a "plug-in", so I'm going to use that term.
The following code shows one way to implement a factory pattern. The reason for having a separate factory object is that your main application can be ignorant of the concrete types in the plug-in dll that implement various interfaces. It only has to be aware of the interfaces and the existance of a single concrete type (the factory).
// Shared interface definition file namespace Environment { public interface IFactory { object GetInterface(Type interfaceType); } public interface ISomeInterface { } } // Plug-in DLL namespace Environment { public class Factory : IFactory { public object GetInterface(Type interfaceType) { if (interfaceType == typeof(ISomeInterface)) return new SomeObject(); // else if (...) return null; } } public class SomeObject : ISomeInterface { } } // Application that makes use of Plug-in DLL namespace SomeApp { // Handy helper class public static class PlugInFactory { private static Environment.IFactory factory; public static object GetInterface(Type interfaceType) { if (factory == null) factory = (Environment.IFactory)Activator.CreateInstanceFrom("MyPlugIn.dll", "Environment.Factory"); return factory.GetInterface(interfaceType); } } public static class Program { static void Main() { // Anywhere in your program you can get a new instance of an // object that implements a specific interface Environment.ISomeInterface instance = (Environment.ISomeInterface)PlugInFactory.GetInterface(typeof(Environment.ISomeInterface)); } } }
- Proposed as answer by Louis.fr Monday, January 18, 2010 9:31 AM
- Marked as answer by Bin-ze Zhao Wednesday, January 20, 2010 3:11 AM
Saturday, January 16, 2010 7:23 PM