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 次:一次调用返回服务的方法,一次创建新对象,一次调用服务的插入方法。

您可以通过依赖注入控制反转来隔离其中的一些复杂性。例如,创建一个像这样的泛型方法:

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

现在,您只需要使用一次反射来调用该方法,而不是三次。

于 2013-04-12T22:39:08.377 回答