0

I have a factory defined like so :

  public IPopulator CreatePopulator<T>(ReportItem Item) where T : IReportElement
    {
        if (typeof(T) == typeof(BarChartElement))
        {
            return BarChartPopulator.Create(Item);
        }
        else
        {
            throw new NotSupportedException(string.Format("Type: {0} is not suppported by {1}", typeof(T).Name, this.GetType().Name));
        }
    }

In the class that calls this method I have a variable like this:

IReportElement MyElement { get; set; }

Assuming MyElement is instantiated to a type that implements IReportElement, How can I call my factory using this variable ?

I have tried

Type VariableType = MyChartElement.GetType();
PopulatorFactory.CreatePopulator<VariableType>(new Chart());

And

PopulatorFactory.CreatePopulator<MyVariable.GetType()>(new Chart());

I could write a switch statement but I feel like there should be some way for me to pass my type. Is this possible ?

BentOnCoding
  • 27,307
  • 14
  • 64
  • 92
  • It's possible with reflection. Is this an option in your case? – agent-j Jun 23 '11 at 21:33
  • reflection is an option. – BentOnCoding Jun 23 '11 at 21:35
  • 1
    I think this is a duplicate of [How to use Reflection to call Generic Method](http://stackoverflow.com/questions/232535/how-to-use-reflection-to-call-generic-method). – Ken Wayne VanderLinde Jun 23 '11 at 21:38
  • If you have the option of changing the factory interface, I would recommend passing in the Type as a 'type' parameter to the method, rather than making the method generic. Since the return type is already an interface rather than the generic parameter type, you don't really gain anything by making it generic and it adds complexity when you want to use it for a type known only at runtime. – Dan Bryant Jun 23 '11 at 21:39

2 Answers2

3

You can't use variables as generic arguments like that. The only way they can provide type safety is if the type is known at compile time.

Factory methods as you describe to tend to be implemented as switch statements, and there is nothing inherently wrong with that. You can pass an enumerated type to your factory method which will in turn return an instance of a type that implements IReportElement.

I don't quite get what you are trying to accomplish here anyway. Your generic factory method is checking the type of the argument. If you have to check the type then, well, it ain't generic anymore, so what's the point?

Perhaps you could go into a bit more depth as to what problem you are actually trying to solve with this code. There may be a better alternative that you have not yet considered.

Ed S.
  • 122,712
  • 22
  • 185
  • 265
  • I simplified the code for example purposes.. this is not the actual implementation of the factory as its much bigger. Switch statements vs if statements are unimportant implementation details. What would you say about using reflection to get the type of the variable ? – BentOnCoding Jun 23 '11 at 21:46
  • I would say that should be a last resort. If it can be accomplished in a simpler, type safe, and more efficient manner than it should be. – Ed S. Jun 23 '11 at 21:57
  • Its not critical. When i Refactor I take DRY Principles to the limit lol. – BentOnCoding Jun 23 '11 at 22:00
2

If you are working with a library that cannot change to be like @Dan Bryant suggested, something like this ought to work.

typeof (PopulatorFactory)
  .GetMethod("CreatePopulator")
  .GetGenericMethodDefinition()
  .MakeGenericMethod(new[] {myVariable.GetType()})
  .Invoke(null, new object []{new Chart ()});
agent-j
  • 27,335
  • 5
  • 52
  • 79