Can I use Activator.CreateInstance with an Interface?

前端 未结 6 1366
故里飘歌
故里飘歌 2021-01-04 00:21

I have an example:

        Assembly asm = Assembly.Load(\"ClassLibrary1\");
        Type ob = asm.GetType(\"ClassLibrary1.UserControl1\");
        UserContro         


        
相关标签:
6条回答
  • 2021-01-04 00:46

    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();

    0 讨论(0)
  • 2021-01-04 00:47

    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();
    
    0 讨论(0)
  • 2021-01-04 00:53

    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>();
    
    0 讨论(0)
  • 2021-01-04 00:54

    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);
        }
    
    0 讨论(0)
  • 2021-01-04 00:56

    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.

    0 讨论(0)
  • 2021-01-04 01:00

    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.

    0 讨论(0)
提交回复
热议问题