2012-09-11 79 views
3

我有在碱库项目中定义的以下接口:实现一个基本接口问题

public interface IWorkContext { 
    T User<T>() where T : IUser; 

    // Note this method is kind of a shortcut so i don't 
    // have to keep passing in T 
    IUser User(); 
} 

public interface IUser { 
    int Id { get; } 
    string UserName { get; } 
} 

现在我有另一个项目,该项目引用上面与下面的类(它实现IUSER)之一。

public class User : IUser { 
    public virtual int Id { get; set; } 
    public virtual string UserName { get; set; } 
    // ... Code removed for brevity 
} 

现在我还需要实现IWorkContext。这是我第一次尝试:

public class DefaultWorkContext : IWorkContext { 
    private readonly IUsersService _usersService; 

    public DefaultWorkContext(IUsersService usersService) { 
     _usersService = usersService; 
    } 

    public T User<T>() where T : IUser { 
     return _usersService.GetUser<T>(1)); 
    } 

    public User User() { 
     return User<User>(); 
    } 
} 

然而,这给出了错误:

The type 'T' cannot be used as type parameter 'T' in the generic type or method '...GetUser(int)'. There is no boxing conversion or type parameter conversion from 'T' to 'User'.

我敢肯定有一些基本的东西,我做错了。我会很感激这个模型的任何建议都可以改进。由于

编辑(这里要求是对的getUser方法):

public T GetUser<T>(int id) where T : User { 
    return _session.Get<T>(id); 
} 

注:_session是NHibernate的会议。

+0

GetUser()返回什么? – itsme86

+0

我们可以为您的UserService和GetUser 方法提供代码吗? –

+0

另外,GetUser接受什么样的泛型?我怀疑这个错误来自这里。 – dureuill

回答

2

这里的问题是,你将泛型的类型参数的GetUser()方法,即可能不能满足你的GetUser()方法接受的泛型类型的继承的条件。

编译器确保作为参数传递的类型始终满足类型条件。 事实上,你可以编写一个class NotUser实现IUser而不是User。 你User<T>()方法可以然后NotUser作为类型参数调用,这将导致对GetUser()通话与不从User继承类型参数。

您的GetUser()方法只接受从User继承的类型。

您需要更改GetUser()原型接受一个实现IUser泛型类型,或User<T>原型只接受泛型类型,从User继承。

无论是这样的:

public T GetUser<T>(int id) where T : IUser { 
    return _session.Get<T>(id); 
} 

或本:

public T User<T>() where T : User { 
    return _usersService.GetUser<T>(1)); 
} 

编辑: 你是否应该选择第一个或第二个方法取决于你想要做什么。

1)您希望您的IWorkContextIUser接口工作,你接受GetUser()方法返回一个IUser =>挑选项1

2)您希望GetUser()方法采取的是从继承的类型User,并且您接受IWorkContext接口与User配合使用,而不是IUser =>选择选项2,并修改接口IWorkContext

对我来说,选项1)更好,因为您不需要修改接口,也不会破坏通用性。但这取决于你想要做什么。

+0

我也在想,但是由于User实现了IUser,我认为它能够接受它。 – itsme86

+0

看我的例子。可能有一个实现IUser的类,但不会从用户继承。最强的条件总是由编译器强制执行,以避免类型不一致(我的意思是,如果需要User类型,GetUser可以使用特定于User的方法或字段,而不是IUser) – dureuill

+0

@ itsme86多态性doesn'像这样反向工作。 –