C#:通过开放的通用方法/类,构造类型约束了打开通用接口的半闭合通用实现



我正在尝试构建一个开放通用存储库接口的实例,从而实现了比接口更严格的类型约束。存储库接口的每个实现都需要对通用类型的特定实现,以根据传递的类型的属性处理某些方法/操作(不是为了简短而显示(。

这是场景的全面示例:

public interface IRepository<T> where T : class
{
    //...
}
public class BaseRepository<T> : IRepository<T> where T : DbModel
{
    //...
}
public class SqlServerDbRepository<T> : BaseRepository<T> where T : SqlServerDbModel
{
    //...
}
public abstract class DbModel
{
    //...
}
// is further derived by other models
public class SqlServerDbModel : DbModel
{
    //...
}
public class User : SqlServerDbModel
{
}
// CLIENT CODE
public static IRepository<T> BuildRepository<T>()
    where T : class
{
    if (typeof(T) == typeof(SqlServerDbModel)) // "is" keyword will not work here (according to IDE, have not checked)
    {
        return new SqlServerDbRepository<T>(); // How can T be converted or accepted as an input of type "SqlServerDbModel" (the check already confirms it, so we know it should work)
    }
    else if (typeof(T) == typeof(DbModel))
    {
        return new BaseRepository<T>(); // How can T be converted or accepted as an input of type "DbModel" (the check already confirms it, so we know it should work)
    }
    //... else throw error or just return default...
}
// USAGE
public static void TestBuildRepository()
{
    var userRepository = BuildRepository<User>();
}

我尝试最初通过IOC容器运行该方案(Castle Windsor,以防万一有人想知道(,以确定它会自动找出类型的约束,但是,这是不可能的(或至少不适合其处理打开通用的方式和依赖注射(。我认为我可以使用自定义工厂来构建接口实现。

问题在与模式return new XYZRepository<T>();匹配的行中,我不确定如何使C#编译器将传递给它的通用类型" T"传递给它,知道它将完全满足类型的约束。我相信这可以通过反思来完成,但是我只找到了有关如何构建方法和属性而不是通用类的信息。如何实现?

我无法对接口,存储库实现或模型进行任何更改...以防万一有人要提出该建议。

我认为您正在寻找这样的东西:

    public static IRepository<T> BuildRepository<T>() where T : class
    {
        if (typeof(T) == typeof(SqlServerDbModel))
        {
            return (IRepository<T>)new SqlServerDbRepository<SqlServerDbModel>();
        }
        if (typeof(T) == typeof(DbModel))
        {
            return (IRepository<T>)new BaseRepository<DbModel>();
        }
        // ...
    }

它有助于解决问题,事实证明,它比我最初预期的要容易。@cragin的答案给了我最后的缺失作品(就...哦,是的,我们可以在c#中进行接口(。

以防将来的任何人偶然发现...

public static IRepository<T> BuildRepository<T>(params object[] constructor_arguments)
    where T : class
{
    if (typeof(T) == typeof(SqlServerDbModel))
    {
        return (IRepository<T>)Activator.CreateInstance(typeof(SqlServerDbRepository<>).MakeGenericType(typeof(T)), constructor_arguments);
    }
    else if (typeof(T) == typeof(DbModel))
    {
        return (IRepository<T>)Activator.CreateInstance(typeof(BaseRepository<>).MakeGenericType(typeof(T)), constructor_arguments);
    }
    //... else throw error or just return default...
}

我需要使用Activator.createinstance API制作对象,然后将其施加回正确的类型。我希望有一种方法可以在温莎城堡"本地"中进行此操作,而无需诉诸自定义工厂/反思。

相关内容

  • 没有找到相关文章

最新更新