【问题标题】:C# Generics: Better Way to Match the Generic's Type to Another?C# 泛型:将泛型类型与另一个匹配的更好方法?
【发布时间】:2010-12-26 15:42:13
【问题描述】:

更新:没有给出一个很好的例子。希望现在好多了。

有没有比这更好的方法:

(typeof(TRepository) == typeof(UserClass))

这里是写的用途:

public static IBaseRepository<TClass> GetRepository<TClass>() where TClass : IDataEntity
{
  IBaseRepository<TClass> repository = null;

  if (typeof(TClass) == typeof(UserClass))
  {
     repository = (IBaseRepository<TClass>)new UserClassRepository();
  }

  if (typeof(TClass) == typeof(PostClass))
  {
     repository = (IBaseRepository<TClass>)new PostClassRepository();
  }

  return repository;
}

如果这样的事情运行很多次,我希望有比运行 typeof 很多次更好的方法。

【问题讨论】:

  • 你想完成什么? typeof(TRepository) == typeof(FiftyPostUser) 应该总是总是为假。

标签: c# generics typeof


【解决方案1】:

你在这里做的是一个穷人的inversion of control container。系好安全带,学习dependency injectioninversion of control的概念,然后你就可以写出这样的代码了:

IIoCContainer container = new IoCContainer();
container.RegisterType<IBaseRepository<UserClass>, UserClassRepository>();
container.RegisterType<IBaseRepository<PostClass>, PostClassRepository>();
var userClassRepository = container.Resolve<IBaseRepository<UserClass>>();

您可以在运行时(如上)或在配置文件中配置容器。您可以指定对象的生命周期(瞬态、单例、每个线程或自定义)。依赖注入容器旨在帮助创建对象,尤其是复杂的对象结构和依赖,编码到接口而不是具体类型(不再是new ConcreteType())和组件配置。

(顺便说一句,从你的类名中去掉后缀Class(所以UserPost,而不是UserClassPostClass)。)

【讨论】:

  • 后缀仅用于示例。实际上,我工作的地方运行着 IoC 的想法,但我不确定我是否已准备好应对任何个人事务上的复杂事情。宝贝在这一点上试图自己弄清楚。
  • 似乎是坐下来花一天时间学习这个概念的好机会。你会在余生中收获回报。
【解决方案2】:

正确的检查是:

if (typeof(TRepository).IsAssignableFrom(typeof(UserClass)))

此外,如果 UserClassRepository 实际上是从 IBaseRepository 派生的,则不需要强制转换它。

事后才想到 - 你为什么要这样做?我确信有更好的方法可以以更可重复的方式实现您想要的。

【讨论】:

  • 强制转换是必需的,因为IBaseRepository&lt;UserClass&gt; 本身不能分配给IBaseRepository&lt;T&gt; 类型的变量。
  • 有点扭曲,但试图从另一个人的角度设计一些易于使用的东西。基本上,这个人不必只知道实体类型就知道存储库类型。希望 IBaseRepository 上有最基本和最常用的方法,因此不需要强制转换。
  • @dtb - T 仅限于 IDataEntity,这意味着 UserClass 必须实现 IDataEntity
  • @programmin 工具 - 你在使用 DI 容器吗?这是抽象出具体实现的最佳方式。
【解决方案3】:

您还没有真正定义“更好”的含义。但是,我可能会采取的一种方法是为定义存储库的每个 TClass 创建一个自定义属性,并在您的 GetRepository 方法中读取此属性。它使用了一些反射,但它比大型 if-else 更优雅,并且比成熟的依赖注入框架更轻量级。快速示例:

属性:

[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public class RepositoryAttribute : Attribute
{
    public RepositoryAttribute(Type repositoryType)
    {
        this.RepositoryType = repositoryType;
    }

    public Type RepositoryType { get; private set; }
}

实体类:

[Repository(typeof(UserClassRepository))]
public class UserClass
{
    // Class code
    // ...
}

工厂方法:

public static IBaseRepository<TClass> GetRepository<TClass>()
  where TClass : IDataEntity
{
    Type t = typeof(TClass);
    RepositoryAttribute attr =
        (RepositoryAttribute)Attribute.GetCustomAttribute(t,
          typeof(RepositoryAttribute), false);
    if (attr != null)
    {
        return (IBaseRepository<TClass>)Activator.CreateInstance(attr.RepositoryType);
    }
    return null;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-08-09
    • 2010-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-25
    相关资源
    最近更新 更多