简体   繁体   English

C#泛型:将通用类型与另一类相匹配的更好方法是什么?

[英]C# Generics: Better Way to Match the Generic's Type to Another?

UPDATE: Didn't give a great example. 更新:没有举一个很好的例子。 Hopefully it's better now. 希望现在好多了。

Is there a better way than this: 有没有比这更好的方法:

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

Here's the use in writing: 这是写作的用法:

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;
}

If something like this is run a lot, I hope there's better way than running typeof a bunch of times. 如果像这样的东西运行很多,我希望有比运行类型更好的方法。

What you're doing here is a poor man's inversion of control container . 你在这里做的是一个穷人的控制容器倒置 Buckle up, learn the concepts of dependency injection and inversion of control and then you can write code like this: 扣紧,学习依赖注入控制反转的概念,然后你可以编写如下代码:

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

You can configure the container at runtime (as above) or in a configuration file. 您可以在运行时(如上所述)或配置文件中配置容器。 You can specify the object lifetime (transient, singleton, per thread, or custom). 您可以指定对象生存期(瞬态,单例,每个线程或自定义)。 Dependency injection containers are intended to assist with object creation, especially for complex object structures and dependencies, coding to interfaces instead of concrete types (no more new ConcreteType() ) and component configuration. 依赖注入容器旨在帮助创建对象,特别是对于复杂的对象结构和依赖项,编码到接口而不是具体类型(不再是new ConcreteType() )和组件配置。

(By the way, drop the suffix Class from you class names (so User and Post , not UserClass and PostClass ).) (顺便说一句,从你的类名中删除后缀Class (所以UserPost ,而不是UserClassPostClass )。)

the correct check would be: 正确的检查将是:

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

additionally, if UserClassRepository is in fact derived from IBaseRepository, you don't need to cast it. 另外,如果UserClassRepository实际上是从IBaseRepository派生的,那么您不需要强制转换它。

As an afterthought - why are you doing it this way? 作为事后的想法 - 你为什么这样做呢? I'm sure there's a much better way to achieve what you want in a more repeatable manner. 我敢肯定,有一种更好的方式可以以更可重复的方式实现你想要的东西。

You haven't really defined what you mean by "better." 你还没有真正定义“更好”的意思。 However, one way I might go about this is to create a custom attribute for each TClass that defines the repository, and read this attribute in your GetRepository method. 但是,我可以采用的一种方法是为每个定义存储库的TClass创建自定义属性,并在GetRepository方法中读取此属性。 It uses some Reflection, but it's more elegant than a big if-else, and more lightweight than a full-fledged dependency-injection framework. 它使用了一些反射,但它比一个大的if-else更优雅,并且比完整的依赖注入框架更轻量级。 Quick example: 快速举例:

Attribute: 属性:

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

    public Type RepositoryType { get; private set; }
}

Entity class: 实体类:

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

Factory method: 工厂方法:

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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM