tags:

views:

139

answers:

3

Ts there any way to call a static member on type when I only have a generic parameter. For example if I have something like this

public Get<T>(int id)
{
   // I would like to do this
   string s = T.SomeMethodName();
}

I could do it like this but is kinda "yucky", and then it does not matter if it is static or not. Or I could use reflection as suggested by Yuriy.

ISomeKnownInterface i = (ISomeKnownInterface ) new T(); 
string s = i.SomeMethodName();

So question is now which is better approach, creating new instance of using reflection

public TFormDto Get<TFormDto>(int entityId) where TFormDto : AbstractEntityFormDto, new()
        {
// create new instance
            AbstractEntityFormDto a = (AbstractEntityFormDto) new TFormDto();
            string entityName = a.GetEntityFullTypeName();

// use reflection 

            Type type = typeof(TFormDto);
            string entityName = type.GetMethods(BindingFlags.Public | BindingFlags.Static)
                .Single(m => m.Name == "GetEntityFullTypeName")
                .Invoke(null, null);
+1  A: 

Wouldn't that just always be AbstractBaseClass.GetFullName(). Otherwise you have to use reflection on T to get the static method of another class. This might be helpful.

The following is a simple example:

class TestClass
{
    public static void Hello()
    {

        Console.WriteLine("World!!!");
    }
}

public static void Test<T>() where T : class
{
    Type type = typeof(T);
    type.GetMethods(BindingFlags.Public | BindingFlags.Static)
        .Single(m => m.Name == "Hello")
        .Invoke(null, null);

}

With your sample, I assume you know interfaces don't have static methods. I assumed you meant you had an interface which has a signature for the static method and a class implementing said interface would just call the static method from the implementation. That would work as well, but you're not guaranteed the correct static will be called and make sure T has a constraint on that interface, not just new().

Yuriy Faktorovich
Yes it would. It is left over from me trying to define abstract static, which is not allowed.
epitka
Would invoking method via reflection like this be faster then just doing something like this. It is kinda yucky to new it up like this but hey this is framework code AbstractEntityFormDto v = (AbstractEntityFormDto) new TFormDto(); string s = v.EntityFullTypeName;
epitka
Can you edit your question, I'm confused about what you just wrote in that format.
Yuriy Faktorovich
Yes, yes I know all of that. Basically I now have abstract class that is subtyped and non-static method just returns a value of the static property. For this I use reflection
epitka
+1  A: 

The problem is there's no guarantee that T has a static member method named SomeMethodName. If you mean to call AbstractBaseClass.SomeMethodName, then do so. The rationale for why this is impossible is an extension of the static interface methods discussion.

280Z28
To bad we don't have constraint for method on generic parameter. That would solve my issue.
epitka
A: 

There is no way to do this without using reflection. To call a static method, you always need to specify the actual type.

If you want to improve the compile-time safety of your code, you would try to avoid reflection. Make the method non-static and put it in an interface. This would most probably (I don't know your problem) be the cleanest solution.

I made quite a few members non-static just to benefit from interfaces and polymorphism. Sometimes I implement something similar to the singleton pattern (eg. static property to get an instance), or just call the default constructor to get an instance and and pass it as argument.

interface ISomeInterface
{
  string SomeMethodName();
}

class SomeImplementation : ISomeInterface
{
  public static Instance { get { return new SomeImplementation(); } }

  public string SomeMethodName()
  {
    // implementation of SomeMethodName
  }
}

public Get(ISomeInterface i)
{
   string s = i.SomeMethodName();
}

public Example()
{
  Get(SomeImplementation.Instance);
}


You may also create the new instance in the generic method, you can also specify that you need a default constructor:

public Get<T>() where T : ISomeInterface, new()
{
   T instance = new T();
   string s = instance.SomeMethodName();
}

public Example()
{
  Get<SomeImplementation>();
}
Stefan Steinegger
The problem is that I don't have an instance just a generic parameter. So basically my options are to new-up the instance and get the value or to use reflection.
epitka
Can't you change the interface of your method with the generic parameter?
Stefan Steinegger
In this case I cannot change the method signature, it has to have generic parameter.
epitka
You can't even change the constraints?
Stefan Steinegger
I can change that, certainly, otherwise I would not be able to create a new instance without new constraint
epitka
Late binding using reflection seems to be the norm these days, just look at ASP.NET MVC.
Yuriy Faktorovich
I would still prefer compile time safety. its important for maintainability. There is no "norm" at all, there are just many libraries using reflection.
Stefan Steinegger