views:

213

answers:

3

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.

+2  A: 

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.

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.

Luke Schafer
The cast is required, because an `IBaseRepository<UserClass>` cannot be assigned to a variable of type `IBaseRepository<T>` per se.
dtb
Screwing around somewhat but trying to design something easy to use from a another person's stand point. Basically so the person doesn't have to know the repository type just the entity type. Hopefull the IBaseRepository will have the most basic and used methods on it so no casting will be needed.
Programmin Tool
@dtb - T is limited to IDataEntity, which means UserClass must implement IDataEntity
Luke Schafer
@programmin tool - are you using a DI container? That is the best way to abstract the concrete implementation away.
Luke Schafer
+5  A: 

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.

(By the way, drop the suffix Class from you class names (so User and Post, not UserClass and PostClass).)

Jason
Suffix is just there for the example.Actually where I work runs the IoC idea but I'm not sure I'm ready for something that complex on any personal stuff. Baby stepping at this point by trying to figure it out myself.
Programmin Tool
Seems like a great opportunity to sit down and spend a day learning the concept. You'll reap the rewards for the rest of your life.
Jason
A: 

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. It uses some Reflection, but it's more elegant than a big if-else, and more lightweight than a full-fledged dependency-injection framework. 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;
}
Aaronaught