InvalidCastException:Activator.CreateInstance w / Generic Inheriting Type

时间:2011-04-01 10:50:28

标签: c# .net generics inheritance .net-4.0

我有一组类都参与了一个继承链,列在本文的底部,最后两种类型和后面的方法是抽象库的一部分,第一类是这样的用法。

我遇到的问题是使用UserService实例化Activator.CreateInstance类型 - InvalidCastException阻止我死亡;虽然这确实很常见,所以我可能只是忽略了我最近巧妙地(或愚蠢地)改变的东西。

正如在运行时创建此实例的方法中所详述的,这是导致错误的代码:

return (IDataService<DataContextType, DataConnectionProviderType, DataEntityType>)Activator.CreateInstance(service); 

但是,以下代码成功:

var a = new UserService();
var b = (UserService<DataContext, ConnectionProvider, User, UserRole>)a;
var c = (DataService<DataContext, ConnectionProvider, User>)b;
var d = (IDataService<DataContext, ConnectionProvider, User>)c;

var e = (IDataService<DataContext, ConnectionProvider, User>)a;

任何人都可以看到我不能做到的事情吗?

不完全确定这里发生了什么,但预感可能与IDataEntity的输入有关。您的考试代码,询问您是否需要更多:

public class UserService
    : UserService<DataContext, ConnectionProvider, User, UserRole>
{
}

public class UserService<DataContextType, DataConnectionProviderType, UserType, UserRoleType>
    : DataService<DataContextType, DataConnectionProviderType, UserType>
    where DataContextType : DataContext<DataConnectionProviderType>, new()
    where DataConnectionProviderType : DataConnectionProviderBase, new()
    where UserType : class, IUser<UserRoleType>, IDataEntity
    where UserRoleType : class, IUserRole, IDataEntity
{
}

public abstract class DataService<DataContextType, DataConnectionProviderType, DataEntityType> 
    : IDataService<DataContextType, DataConnectionProviderType, DataEntityType>
        where DataContextType : DataContext<DataConnectionProviderType>, new()
        where DataConnectionProviderType : DataConnectionProviderBase, new()
        where DataEntityType : class, IDataEntity
{
}

public interface IDataService<DataContextType, DataConnectionProviderType, DataEntityType> : IDisposable
    where DataContextType : DataContext<DataConnectionProviderType>, new()
    where DataConnectionProviderType : DataConnectionProviderBase, new()
    where DataEntityType : class, IDataEntity
{
}

public static IDataService<DataContextType, DataConnectionProviderType, DataEntityType>
    LoadServiceType<DataContextType, DataConnectionProviderType, DataEntityType>(Type service)
    where DataContextType : DataContext<DataConnectionProviderType>, new()
    where DataConnectionProviderType : DataConnectionProviderBase, new()
    where DataEntityType : class, IDataEntity
{
    ...

    return (IDataService<DataContextType, DataConnectionProviderType, DataEntityType>)Activator.CreateInstance(service);             
}

例外详细信息:

System.InvalidCastException: Unable to cast object of type '...UserService' to type '...IDataService'3[...DataContext,...Domain.Data.ConnectionProvider,...IDataEntity]'.

1 个答案:

答案 0 :(得分:3)

看起来你正在打电话:

LoadServiceType<DataContext, ConnectionProvider, IDataEntity>(typeof(UserService));

那是行不通的,因为它试图转向

IDataService<DataContext, ConnectionProvider, IDataEntity>
UserService实际实现

IDataService<DataContext, ConnectionProvider, User>

您会发现,如果您更改测试代码以尝试使用IDataEntity作为类型参数而不是User进行投射,则会以相同的方式失败。

这与泛型差异有关。这是一个很大的话题 - Eric Lippert有一个whole series of blog posts on it,去年我在NDC上发表了一个演讲...我不知道有关谈话的流媒体网站是否仍然可用,但你可以抓住一个所有谈话的洪流here

举一个非常简单的例子,你不能以完全相同的方式将IList<string>强制转换为IList<object> - 否则这会编译,但必须在执行时失败:

IList<string> strings = new List<string>();
IList<object> objects = strings;
objects.Add(new object());
string firstString = strings[0]; // Eek!