问题
I have an example:
Assembly asm = Assembly.Load("ClassLibrary1");
Type ob = asm.GetType("ClassLibrary1.UserControl1");
UserControl uc = (UserControl)Activator.CreateInstance(ob);
grd.Children.Add(uc);
There I'm creating an instance of a class, but how can I create an instance of a class which implements some interface? i.e. UserControl1 implements ILoad interface.
U: I can cast object to interface later, but I don't know which type in the assemblies implements the interface.
回答1:
This is some code i have used a few times. It finds all types in an assembly that implement a certain interface:
Type[] iLoadTypes = (from t in Assembly.Load("ClassLibrary1").GetExportedTypes()
where !t.IsInterface && !t.IsAbstract
where typeof(ILoad).IsAssignableFrom(t)
select t).ToArray();
Then you have all types in ClassLibrary1 that implement ILoad
.
You could then instantiate all of them:
ILoad[] instantiatedTypes =
iLoadTypes.Select(t => (ILoad)Activator.CreateInstance(t)).ToArray();
回答2:
You cannot create instance of an interface, but if
UserControl1 implements ILoad inteface
you can use resulting object as ILoad
ILoad uc = (ILoad)Activator.CreateInstance(ob);
grd.Children.Add(uc);
Moreover, you do not need to treat it via interface, if you write
UserControl1 uc = (UserControl1)Activator.CreateInstance(ob);
grd.Children.Add(uc);
Members of ILoad
would be callable as uc.SomeILoadMethod();
回答3:
What you want can be achieved using a IoC container like `NInject'. You can configure a container to return a concrete type when you've requested an interface.
回答4:
The only problem with the accepted answer is that you must have a concrete class on your assembly that implements the interface.
To avoid that I have created my CustomActivator that is able to create a dynamic object at runtime and make it implements the desired interface.
I put it on the github: https://github.com/fabriciorissetto/CustomActivator
The call is simple:
CustomActivator.CreateInstance<MyInterface>();
回答5:
Interface is an interface. It's a template. Why would you want to instantiate an interface? Implement the interface and instantiate that class. You can't instantiate an interface, it doesn't really make sense.
回答6:
If the library was referenced in the project you may use:
static public IEnumerable<Type> GetTypesFromLibrary<T>(String library)
{
var MyAsemblies = AppDomain.CurrentDomain.GetAssemblies()
.Where(a=>a.GetName().Name.Equals(library))
.Select(a=>a);
var Exported = MyAsemblies
.FirstOrDefault()
.GetExportedTypes();
var Asignable = Exported
.Where (t=> !t.IsInterface && !t.IsAbstract
&& typeof(T).IsAssignableFrom(t))
.Select(t=>t)
.AsEnumerable();
return Asignable;
}
static public T GetInstanceOf<T>(String library, String FullClassName)
{
Type Type = GetTypesFromLibrary<T>(library)
.Where(t => t.FullName.Equals(FullClassName))
.FirstOrDefault();
if (Type != null)
{
T Instance = (T)Activator.CreateInstance(Type);
return Instance;
}
return default(T);
}
来源:https://stackoverflow.com/questions/10732933/can-i-use-activator-createinstance-with-an-interface