6

我有以下接口和实现:

public interface IRepository<T>
{
    IList<T> GetAll();
}

internal class TrendDataRepository : IRepository<TrendData>
{
    public IList<TrendData> GetAll()
    {
        //.. returns some specific data via Entity framework
    }
}

我将有多个实现,它们都通过实体框架返回不同的数据。在某些时候,我想向用户表示一个实现 IRepository 接口的类的列表。我使用以下代码执行此操作。这对我很有用。

    public static IEnumerable<string> GetAvailableRepositoryClasses()
    {
        var repositories = from t in Assembly.GetExecutingAssembly().GetTypes()
                           where t.GetInterfaces().Any(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof (IRepository<>))
                           select t.Name;

        return repositories;
    }

但是,我还想创建一个工厂方法,给定一个特定的字符串将返回一个具体的存储库类型,并允许我调用它的“GetAll”方法。在伪代码中:

someObject = Factory.CreateInstance("TrendData");
someObject.GetAll();

(我知道这行不通,因为我必须在工厂方法中指定具体类型)。

我想要这个功能,因为我想让用户能够将报表绑定到特定的数据源。通过这种方式,他们可以启动一个新报表,其中报表的数据源绑定到(例如)TrendDataRepository.GetAll() 方法。

但是,也许是因为世界末日越来越近了;-) 或者是星期五下午,我无法再清楚地思考,我不知道如何意识到这一点。

一些指针将非常受欢迎。

4

1 回答 1

2

我建议返回存储库类型的集合而不是名称,并仅在 UI 中显示名称:

public static IEnumerable<Type> GetAvailableRepositoryClasses()
{
    return Assembly.GetExecutingAssembly().GetTypes()
        .Where(t => t.GetInterfaces().Any(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof (IRepository<>)));
}

然后,当用户选择源时,您可以执行以下操作:

object repository = Activator.CreateInstance(selectedType);

此方法要求每个存储库都有一个默认构造函数。

Activator.CreateInstance返回一个对象,除非您知道您期望IRepository<T>的泛型类型,否则您不能将其转换为您的界面。最好的解决方案可能是创建一个您的存储库类也实现T的非通用接口:IRepository

public interface IRepository
{
    IList<object> GetAll();
}

现在您可以将创建的存储库转换为IRepository

IRepository repository = (IRepository)Activator.CreateInstance(selectedType);

您可以创建一个实现两者的存储库基类:

public abstract class RepositoryBase<T> : IRepository<T>, IRepository
{
    public abstract IList<T> GetAll();
    IList<object> IRepository.GetAll()
    {
        return this.GetAll().Cast<object>().ToList();
    }
}
于 2012-12-21T13:59:13.033 回答