我可以在接口上使用Activator.CreateInstance吗?

我有一个例子:

        Assembly asm = Assembly.Load("ClassLibrary1");
        Type ob = asm.GetType("ClassLibrary1.UserControl1");
        UserControl uc = (UserControl)Activator.CreateInstance(ob);
        grd.Children.Add(uc);

在那里我创建了一个类的实例,但是如何创建一个实现某个接口的类的实例呢?即 UserControl1 实现 ILoad 界面。

U: I can cast object to interface later, but I don't know which type in the assemblies implements the interface.

0
额外 编辑
意见: 1
您无法创建接口的实例;您可以创建实现该接口的类并将其作为接口传递。
额外 作者 Marco,
你不能实例化ILoad类型的对象,它是一个接口。
额外 作者 JustinDanielson,

6 答案

这是我用过几次的一些代码。它查找实现某个接口的程序集中的所有类型:

Type[] iLoadTypes = (from t in Assembly.Load("ClassLibrary1").GetExportedTypes()
                     where !t.IsInterface && !t.IsAbstract
                     where typeof(ILoad).IsAssignableFrom(t)
                     select t).ToArray();

然后,您可以在ClassLibrary1中实现 ILoad 的所有类型。

然后你可以实例化它们全部:

ILoad[] instantiatedTypes = 
    iLoadTypes.Select(t => (ILoad)Activator.CreateInstance(t)).ToArray();
0
额外
我该如何施放,如果界面是通用的ILoad <>?
额外 作者 barteloma,
谢谢,好的解决方案。
额外 作者 Arman Hayots,
我收到以下错误:找不到源类型为“System.Reflection.Assembly”的查询模式的实现。 '找不到'。
额外 作者 dotNET,
找到了。 Load(“ClassLibrary1”)在上面的代码中应紧跟着 .GetExportedTypes();
额外 作者 dotNET,
@dotNET是的,那个电话应该在那里。我现在添加了它。
额外 作者 Botz3000,
@bookmarker您需要知道类型参数才能投射。如果您不知道,可以使用非通用基础接口。如果不知道类型参数,泛型类或接口就不再那么容易使用了。
额外 作者 Botz3000,
你好。任何想法如何在便携式课程中做到这一点? 't'似乎没有IsInterface或IsAbstract,Type也没有IsAssignableFrom。我试图从一个可移植的类库项目中的一个接口激活一个实例,所以我可以在Xamarin中使用它。
额外 作者 shahar eldad,

你不能创建一个接口的实例,但如果

UserControl1实现了ILoad接口

you can use resulting object as ILoad

ILoad uc = (ILoad)Activator.CreateInstance(ob);
grd.Children.Add(uc);

而且,如果你写的话,你不需要通过接口来处理它

UserControl1 uc = (UserControl1)Activator.CreateInstance(ob);
grd.Children.Add(uc);

Members of ILoad would be callable as uc.SomeILoadMethod();

0
额外
好的,但是我怎么才能在程序集中找到类型,它实现了 ILoad
额外 作者 Arman Hayots,
假设 ob 仍然是代表类而不是接口的类型。
额外 作者 Guillaume,
@Guillaume构造的对象实现了ILoad,因此它可以直接使用
额外 作者 archil,

接口是一个接口。这是一个模板。你为什么要实例化一个接口?实现接口并实例化该类。你不能实例化一个接口,它没有任何意义。

0
额外
当然,有一个实例化接口的简单方法是有意义的。想象一下DTO。没有行为的POCO。您希望将它们创建为接口,以便在模拟框架中轻松使用它们,但是当您实现接口时,基本上最终会产生两个相同的代码段,您需要维护它们。这就是为什么一些框架,如NServiceBus,让你“实例化接口”。我并不是说它可以通过像Activator这样的内置功能轻松完成,我只是说你不能将它吹掉,因为“没有意义”
额外 作者 Morten,

你可以使用像'NInject'这样的IoC容器来实现你想要的。 您可以配置容器以在您请求界面时返回具体类型。

0
额外

如果该库在项目中被引用,您可以使用:

    static public IEnumerable GetTypesFromLibrary(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(String library, String FullClassName)
    {
        Type Type = GetTypesFromLibrary(library)
                        .Where(t => t.FullName.Equals(FullClassName))
                        .FirstOrDefault();
        if (Type != null)
        {
            T Instance = (T)Activator.CreateInstance(Type);
            return Instance;
        }
        return default(T);
    }
0
额外

被接受的答案唯一的问题是你的程序集必须有一个实现接口的具体类。

为了避免这种情况,我创建了我的CustomActivator,它能够在运行时创建一个动态对象并使其实现所需的接口。

I put it on the github: https://github.com/fabriciorissetto/CustomActivator

电话很简单:

CustomActivator.CreateInstance();
0
额外