以正确的方式从另一个程序集实例化接口实现

时间:2016-05-20 16:14:41

标签: c# dll reflection interface .net-assembly

我目前正在开发某种“迷你SDK”,其中包含我常用的有用类和函数。

因此,我制作了几个可以在其他程序集中实现的接口。

所以它基本上是这样的:

// In SDK.dll:

namespace MySDK
{
    public interface IExample
    {
        /* .. */
    }   
}


// In another assembly:

namespace Example
{
    public class Implementation : MySDK.IExample
    {
        /* .. */
    }
}

这没问题。我的问题是,在SDK中我想使用这个接口的实际实现,所以我做的是:

// in SDK.dll

    private IExample GetImplementation(string fileName)
    {
        Type implementation = Assembly
            .LoadFrom(fileName)
            .GetExportedTypes()
            .Where(t =>
                t.GetInterface(typeof(IExample).FullName) != null
                && (t.Attributes & TypeAttributes.Abstract) != TypeAttributes.Abstract)
            .FirstOrDefault();

        if(implementation != null)
        {
            return (IExample)Activator.CreateInstance(implementation);
        }
        else
        {
            return null;
        }
    }

这可以做到并且做我想做的事,但它看起来真的很难看而且不知何故错了。

我不确定,这是正确/最好的方法吗? 还有更好的方法吗?

1 个答案:

答案 0 :(得分:0)

我会将第一部分更改为:

Type implementation = Assembly
        .LoadFrom(fileName)
        .GetExportedTypes()
        .Where(t => typeof(IExample).IsAssignableFrom(t) && !t.IsAbstract)
        .FirstOrDefault();

但是我在代码中看到的更大的问题是它只有在实现类具有无参数构造函数时才有效。你也应该测试一下。

下一个问题是泛型类型。所以我建议:

Type implementation = Assembly
        .LoadFrom(fileName)
        .GetExportedTypes()
        .Where(t => 
            typeof(IExample).IsAssignableFrom(t) && 
            !t.IsAbstract &&
            !t.IsGenericType &&
            t.GetConstructors(BindingFlags.Public).Any(c => !c.GetParameters().Any())
        .FirstOrDefault();

但这种方法可能存在其他问题。