T type dynamic general declaration

I have an array that stores a type dictionary:

//The dictionary: Dictionary<CacheKey,Type> TypeLookup; //This is the enum: public enum CacheKey { UserProfile, CustomerQuickSearch, CommissionConfiguration } 

I would like to use this Dictionary to declare a variable of type T

  //instead of T myvar; //I want to dynamically declare myvar as: //1)get the type for the cacheKey from the dictionary: Type type = TypeLookup[cacheKey]; //2)declare myvar as the corresponding Type: type myvar; 

It is assumed that I am creating a distributed caching infrastructure. I have a very small CachingProvider that allows you to update an item in the cache.

I would like to open this method as a web service so that all servers in my farm can update their cache. But I would like to have only one method open as a web service, which then updates the corresponding item in the cache.

This is the method I'm trying to open:

  public static void UpdateCacheEntryItem<T>(CacheKey cacheKey, int id) { //look up the cacheEntry in cache which is a dictionary. Dictionary<int, T> cacheEntry = (Dictionary<int, T>) CacheRef[cacheKey.ToString()]; //call the corresponding method which knows how to hydrate that item and pass in the id. cacheEntry[id] = (T)HydrateCacheEntryItemMethods[cacheKey].Invoke(id); } 

Things I tried: 1) I tried to expose the method directly as a WCF service, but of course this does not work due to the method. 2) I tried pouring the Dictionary, which will be found, because I do not need to do anything with the return value, I just need to update the item in the cache. But that didn't work either. The error I get: cannot list an object of type 'System.Collections.Generic.Dictionary 2[System.Int32,CachingPrototype.CustomerQuickSearch]' to type 'System.Collections.Generic.Dictionary 2 [System.Int32, System.Object] '.

Your comments were very helpful and helped me answer my question. The solution I came up with is simply to include my WCF method in the switch statement so that I can call the UpdateCacheEntryItem method with the correct type T. Since there is no way to convert from Type to a general T operator, this is the only option. Since I don't have many types in the cache, this works very well. (Another solution would be to use an interface as indicated below, but that would not be as strong as we would like.)

  [OperationContract] public void UpdateCacheEntryItem(CacheKey cacheKey, int id) { switch (cacheKey) { case CacheKey.UserProfile: CacheProvider.UpdateCacheEntryItem<UserProfile>(cacheKey, id); break; case CacheKey.CommissionConfig: CacheProvider.UpdateCacheEntryItem<CommissionConfig>(cacheKey, id); break; case CacheKey.CustomerQuickSearch: CacheProvider.UpdateCacheEntryItem<CustomerQuickSearch>(cacheKey, id); break; default: throw new Exception("Invalid CacheKey"); } 

Thank you all for your help, you are great!

+1
source share
2 answers

The idea of ​​“dynamically declaring a variable” contradicts the whole point that a type exists as part of a variable declaration. The idea is that you can tell the compiler a type so that it can check what you are doing. In this case, you did not provide any type information at all. You can simply declare myVar as an object type; which is basically the same as saying "I know almost nothing about the meaning of myVar , except that it is a link."

If you have a common interface, of course, that would be great - and then you could safely use the members of this interface (after creating / fetching a suitable instance, of course). But otherwise, you really can’t do much if you don’t know something about type at compile time.

In C # 4, you can declare a variable of type dynamic that will do all the dynamic binding - basically you can do what you like, and all this will be allowed at runtime. I would suggest using static typing wherever you are, so that errors can be caught at compile time.

+10
source

It seems to me that the interface and some castings will help solve your problem. It’s just that each of your caching classes implements an interface. Store items of this type in your dictionary. Presumably, CacheRef will be of type Dictionary<CacheKey,Dictionary<CacheKey,ICacheable>> . It remains only to make sure that your caching classes implement the interface.

 public interface ICacheable { } public static void UpdateCacheEntryItem(CacheKey cacheKey, int id) { //look up the cacheEntry in cache which is a dictionary. Dictionary<CacheKey,ICacheable> cacheEntry = CacheRef[cacheKey.ToString()]; //call the corresponding method which knows how to hydrate that item and pass in the id. cacheEntry[id] = (ICacheable)HydrateCacheEntryItemMethods[cacheKey].Invoke(id); } 

Please note that this is not how @Jon Skeet says in his comments on his answer by applying a type in your dictionary. It depends on your code to make sure that you put the right objects in each cache. It would be convenient for me if your hydration methods were covered by unit tests to ensure that with a given key, they always create objects of the appropriate type.

+2
source

All Articles