5

これは私のコードの一部で、助けが必要です:

// simple service locator
public class ServiceManager<TSvc> : IServiceManager<TSvc> where TSvc: class, IService
{
   private Dictionary<object, TSvc> services;

   public void RegisterService(TSvc service)
    {
        // omitted code here
        this.services.Add(service.GetType(), service); // dictionary
    }
    public T GetService<T>() where T : TSvc
    {
        T result = default(T);

        TSvc bufResult = null;
        if (this.services.TryGetValue(typeof(T), out bufResult))
            result = (T)bufResult;

        return result;
    }
    public TSvc GetService(Type serviceType)
    {
        TSvc result = null;

        this.services.TryGetValue(serviceType, out result);

        return result;
    }
}

次に、私のドメイン インターフェイス:

public interface IItem
{
   string Name { get; set; }
}
public interface IRepository<TModel> where TModel : IItem
{
    new IEnumerable<TModel> GetItems();
    void InsertItem(TModel item);
    void UpdateItem(TModel item);
    void DeleteItem(TModel item);
}
public interface IService<TModel> where TModel : IItem
{
    IRepository<TModel> Repository { get; }
}

次に、いくつかのドメイン クラス:

public class Book: IItem
{
    public string Name { get; set; }
}
public class BookRepo: IRepository<Book>
{
    new IEnumerable<Book> GetItems();
    void InsertItem(Book item);
    void UpdateItem(Book item);
    void DeleteItem(Book item);
}
public class BookService: IService<Book>
{
    IRepository<Book> IService<Book>.Repository { get { return this.Repository; } }
    BookRepo Repository { get; set;} 
}

ここで、「BookService」を使用して何かを行うことに興味がある場合は、次のようにサービス ロケーターから取得できます。

public void DoSomething()
{
    var bookService = serviceManager.GetService<BookService>();
    bookService.Repository.Insert(new Book()); 
}

しかし問題は、サービスのタイプが実行時にしか分からないことです (例: コンボボックスからの選択)。では、DoSomething メソッドはどのように見えるでしょうか?

public void DoSomething()
{
    var typeOfService = combobox.SelectedValue.GetType(); // cbx of services
    // ??? make use of serviceManager and typeOfService to get appropriate 'service'
    service.Repository.Insert(/*new IITem here*/);
}

また、どのように接続IServiceしますかIService<TModel>...解決策にたどり着く可能性もありますが、方法がわかりません。私のIServiceインターフェースは今のところ空白です...

お時間をいただき、誠にありがとうございます。不明な点があれば教えてください!ありがとうございました!

更新:あなたの回答に基づいて、リフレクションの部分が関与している可能性があると思います (NSGaga が指摘したようなもの) が、それでも、接続せずにIServiceIService<TModel>私が望むものを達成することはできません。これを再設計する方法を誰が知っていますか?

4

2 に答える 2

2

このようなものはうまくいくはずです(私の頭から入力するので、構文の詳細を確認する必要があります-しかし、指示を与える必要があります-または後で追加します)

MethodInfo methodInfo = typeof(ServiceManager).GetMethod("GetService");
MethodInfo methodInfoGeneric = methodInfo.MakeGenericMethod(new[] { typeOfService });
methodInfoGeneric.Invoke(serviceManager, new object[] { });
于 2013-04-12T22:37:02.190 に答える
2

型が実行時にのみ認識されるジェネリック メソッドを呼び出すには、リフレクションを使用する必要があります。

たとえば、最後のコード サンプルでは、​​ を呼び出すことができないことを正しく暗示してGetService<BookService>いますが、まだサービスに追加new Book()しています。また、リフレクションを使用して新しいオブジェクトをインスタンス化する必要があります。これも、コンパイル時に型がわからないためです。そのため、リフレクションを少なくとも 3 回使用する必要があります。サービスを返すメソッドを呼び出すために 1 回、新しいオブジェクトを作成するために 1 回、サービスの挿入メソッドを呼び出すために 1 回です。

この複雑さの一部は、依存性注入制御の反転で分離できます。たとえば、次のようなジェネリック メソッドを作成します。

void CreateNewObject<T>() where T : new()
{
    var service = GetServiceFor<T>();
    service.Repository.Insert(new T());
}

これで、リフレクションを使用する必要があるのは、そのメソッドを呼び出すのに 3 回ではなく、1 回だけです。

于 2013-04-12T22:39:08.377 に答える