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>();
    }
}

ただし、これによりエラーが発生します。

タイプ「T」は、ジェネリックタイプまたはメソッド「... GetUser(int)」のタイプパラメータ「T」として使用できません。'T'から'User'へのボクシング変換またはタイプパラメータ変換はありません。

私が間違っている根本的なことがあると確信しています。このモデルに関するアドバイスを改善していただければ幸いです。ありがとう

編集(ここで要求されたのはGetUserメソッドです):

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

注:_sessionはNHibernateセッションです。

4

1 に答える 1

2

ここでの問題は、ジェネリック型を型パラメーターとしてGetUser()メソッドに渡していることです。これは、メソッドによって受け入れられるジェネリック型の継承の条件を満たさない可能性がGetUser()あります。

コンパイラーは、パラメーターとして渡される型が常に型の条件を満たすことを保証します。確かに、でなくてclass NotUserも実装するを書くことができます。次に、メソッドを型パラメーターとしてで呼び出すことができます。これにより、から継承しない型パラメーターを使用してへの呼び出しが行われます。IUserUserUser<T>()NotUserGetUser()User

メソッドGetUser()は、から継承するタイプのみを受け入れUserます。

GetUser()を実装するジェネリック型を受け入れるようにプロトタイプを変更するかIUserUser<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));
}

編集: 最初の方法と2番目の方法のどちらを選択するかは、何をしたいかによって異なります。

1)インターフェイスを操作IWorkContextする必要があり、メソッドがa =>pickオプション1を返すIUserことを受け入れます。GetUser()IUser

2)GetUser()メソッドがから継承する型を取得するようにし、 =>オプション2を選択する代わりに、インターフェイスが機能するUserことを受け入れ、インターフェイスを変更します。IWorkContextUserIUserIWorkContext

私にとっては、オプション1)の方が優れています。これは、インターフェイスを変更する必要がなく、汎用性を損なうことがないためです。しかし、それはあなたが正確に何をしたいかによります。

于 2012-09-11T16:08:07.450 に答える