Accessing static methods for a Generic class in C #

I have the following situation in the code, which I suspect might be a little unworthy:

I have a class:

abstract class DataAccessBase<T> : IDataAccess where T : AnotherAbstractClass 

This DataAccessBase class also has a static factory method that instantiates the derived classes themselves using the enum value, in which the operator determines which derived type creates:

 static IDataAccess CreateInstance(TypeToCreateEnum) 

Now the types obtained from DataAccessBase<T> themselves are not common, they indicate the type for T:

 class PoLcZoneData : DataAccessBase<PoLcZone> // PoLcZone is derived from AnotherAbstractClass 

So far, I’m not sure if this pushes the limits of the good use of generics, but what really bothers me is how to access the static CreateInstance() method in the first place:

The way I'm doing this at the moment is to just pass any type to T, where T: AnotherAbstractClass . In particular, I pass AnotherAbstractClass . This allows compilation to be just fine, but it seems to me that passing any type to a common class just to get into statics is a bit unreliable.

I actually simplified the situation, because DataAccessBase<T> is the lower level in the inheritance chain, but static factory methods exist at the middle level, and classes such as PoLcZoneData are the most derived at a single level, which is not common.

What do people think of this arrangement?

+4
source share
3 answers

You are allowed to have a non-generic class with the same name ... maybe something like:

 abstract class DataAccessBase<T> : IDataAccess where T : AnotherAbstractClass { ... } static class DataAccessBase { public static IDataAccess CreateInstance(TypeToCreateEnum) {...} } 

Now you can use DataAccessBase.CreateInstance without excess T Typically, you can call the internal methods on a DataAccessBase<T> from a DataAccessBase - although I suspect you might also need a little reflection / MakeGenericType in your script.

+9
source

I encountered a similar problem a while ago ("how to overload static methods"), and I solved it with Reflection.

Here is my situation:

1) public abstract class AuditObject<T> : ActiveRecordBase<T> (yes, I use ActiveRecord) and

2) public class Employee : AuditObject<Employee>

In both of them, I define some static methods, for example

 public static DataTable GetLookupTable(String where, Int32 topRows) { return doExtremelyCleverStuffToFetchData(where, topRows); } 

(in # 2 you need public **new** static or you get a compiler warning)

Like a code when I call, for example.

 DataTable myList = AuditObject<T>.GetLookupTable("inactive = 0", 100); 

... and T is Employee, the static method is not "redefined", that is, the one that is executed is the method in (1), not (2).

So, in (1) I changed the static methods (in this example GetLookupTable) as follows:

 public static DataTable GetLookupTable(String where, Int32 topRows) { DataTable tbl = null; Boolean hasOverride = hasMethodOverride("GetLookupTable"); if (hasOverride) { tbl = invokeStaticMethod<T>( "GetLookupTable", new Object[2] { where, topRows }) as DataTable; } else { tbl = doExtremelyCleverStuffToFetchData(where, topRows); } return tbl; } 

Here's how I find out if a static method exists:

 private static Boolean hasMethodOverride(String methodName) { var methodQuery = from method in typeof(T).GetMethods( BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod) where method.Name == methodName select method; return methodQuery.Count() > 0; } 

And this is how the override method is called:

 public static Object invokeStaticMethod<T>(String MethodName, Object[] Args) { return typeof(T).InvokeMember(MethodName, BindingFlags.Public | BindingFlags.Static | BindingFlags.InvokeMethod, null, null, Args); } 

Howl! When I call DataTable myList = AuditObject<T>.GetLookupTable("inactive = 0", 100); and T is Employee, I get the results of the static method defined in the Employee class.

Hope this helps,

Dimitris

+2
source

I don’t think that something is wrong with this design, especially if you use the template parameter to indicate the implementation detail. I would suggest that simply the factory function is not static, but simply autonomous. That would be the clearest way to do this for me.

If you want to encapsulate it somehow, I would suggest a namespace or naming convention.

Another solution would be to simply hide what you are doing right now by defining the DataAccessBase type, perhaps like this:

 typedef DataAccessBase<AnotherAbstractClass> DataAccessBaseFactory; 

This is my least recommended solution, but it leaves the Create function as static if you absolutely want it.

0
source

All Articles