Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/335.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么我自己的类型会得到System.InvalidCastException?_C#_Generics - Fatal编程技术网

C# 为什么我自己的类型会得到System.InvalidCastException?

C# 为什么我自己的类型会得到System.InvalidCastException?,c#,generics,C#,Generics,下面我的方法ImplementingInterface获取实现自定义接口的所有类,IInstaller private static IEnumerable<Assembly> MyAssemblies { get { return AppDomain.CurrentDomain.GetAssemblies().Where(x=>x.GetName().Name.StartsWith("ProjectPrefix", StringComparison.OrdinalIg

下面我的方法
ImplementingInterface
获取实现自定义接口的所有类,
IInstaller

private static IEnumerable<Assembly> MyAssemblies
{
    get { return AppDomain.CurrentDomain.GetAssemblies().Where(x=>x.GetName().Name.StartsWith("ProjectPrefix", StringComparison.OrdinalIgnoreCase)); }
}

public static IEnumerable<TInterface> ImplementingInterface<TInterface>() where TInterface : class
{
    var interfaceType = typeof(TInterface);

    if (!interfaceType.IsInterface)
        throw new Exception(interfaceType.Name + " is not an interface.");

    var types = new List<Type>();

    foreach (var assembly in MyAssemblies) 
    {
        types.AddRange(assembly.DefinedTypes.Where(x => x.ImplementedInterfaces.Any(inter => inter == interfaceType)));
    }

    var expectedTypes = types.ToList();
    var interfaces = expectedTypes.Cast<TInterface>().ToList(); // Error occurs.

}
私有静态IEnumerable MyAssembly
{
获取{return AppDomain.CurrentDomain.getAssemblys().Where(x=>x.GetName().Name.StartsWith(“ProjectPrefix”,StringComparison.OrdinalIgnoreCase));}
}
公共静态IEnumerable实现接口(),其中TInterface:class
{
var interfaceType=类型(TInterface);
如果(!interfaceType.IsInterface)
抛出新异常(interfaceType.Name+“不是接口”);
变量类型=新列表();
foreach(MyAssembly中的var程序集)
{
types.AddRange(assembly.DefinedTypes.Where(x=>x.ImplementedInterfaces.Any(inter=>inter==interfaceType));
}
var expectedTypes=types.ToList();
var interfaces=expectedTypes.Cast().ToList();//发生错误。
}
但是当它碰到下面标有
错误的行时,它抛出以下错误:

`System.Core.dll中发生“System.InvalidCastException”类型的异常,但未在用户代码中处理

其他信息:无法将“System.RuntimeType”类型的对象强制转换为“ProjectPrefix.IInstaller”类型`


expectedTypes
有3个类都实现了
IInstaller
,为什么会抛出此错误?

您正在搜索类型-因此您的结果是一个
IEnumerable
。那些
Type
对象不实现您的接口-类型的实例将实现接口

因此,您的代码尝试执行以下操作:

IInstaller installer = typeof(SomeInstaller);
而不是:

IInstaller installer = new SomeInstaller();
如果希望能够强制转换到接口,则需要创建类型的实例。如果您试图动态创建实例,并且它们都有一个公共的无参数构造函数,那么您可以使用
Activator.CreateInstance

// Get rid of the AddRange call... there's no point in that, or calling
// ToList() on something that's already a list. Use LINQ to its fullest :)
return assembly.DefinedTypes
               .Where(t => t.ImplementedInterfaces.Contains(interfaceType))
               .Select(t => Activator.CreateInstance(t))
               .Cast<TInterface>()
               .ToList();

您正在搜索类型-因此您的结果是一个
IEnumerable
。那些
Type
对象不实现您的接口-类型的实例将实现接口

因此,您的代码尝试执行以下操作:

IInstaller installer = typeof(SomeInstaller);
而不是:

IInstaller installer = new SomeInstaller();
如果希望能够强制转换到接口,则需要创建类型的实例。如果您试图动态创建实例,并且它们都有一个公共的无参数构造函数,那么您可以使用
Activator.CreateInstance

// Get rid of the AddRange call... there's no point in that, or calling
// ToList() on something that's already a list. Use LINQ to its fullest :)
return assembly.DefinedTypes
               .Where(t => t.ImplementedInterfaces.Contains(interfaceType))
               .Select(t => Activator.CreateInstance(t))
               .Cast<TInterface>()
               .ToList();

..或检查该类型是否使用该类型的某个方法实现接口。有一个问题你可以问一个实例是否会实现一个接口。@TomTomTom:是的,我已经到了。但是我想先纠正OP代码中最重要的部分:)@JonSkeet感谢我是个白痴,它只把IInstaller作为类型之一,所以
where
应该变成:
.where(t=>interfacepe.IsAssignableFrom(t)和&t.GetConstructor(Type.EmptyTypes)!=null)
@shenku:或者,您可以检测该类型是否是一个具体的类,这将让您找到所有没有无参数构造函数但应该执行的实现……或者检查该类型是否使用该类型的某个方法实现接口。有一个问题你可以问一个实例是否会实现一个接口。@TomTomTom:是的,我已经到了。但是我想先纠正OP代码中最重要的部分:)@JonSkeet感谢我是个白痴,它只把IInstaller作为类型之一,所以
where
应该变成:
.where(t=>interfacepe.IsAssignableFrom(t)和&t.GetConstructor(Type.EmptyTypes)!=null)
@shenku:或者您可以检测该类型是否是一个具体的类,这将让您找到所有没有无参数构造函数但应该有无参数构造函数的实现。