我有一个存储类型字典的数组:
//The dictionary:
Dictionary<CacheKey,Type> TypeLookup;
//This is the enum:
public enum CacheKey
{
UserProfile,
CustomerQuickSearch,
CommissionConfiguration
}
我想使用这个Dictionary来声明一个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;
背景是我正在构建分布式缓存基础结构。我有一个很棒的CachingProvider,它允许你更新缓存中的项目。
我想将此方法公开为Web服务,以便我的服务器场中的所有服务器都可以更新其缓存。但我希望只有一个方法作为Web服务公开,然后更新缓存中的相应项目。
这是我试图揭露的方法:
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);
}
我尝试过的事情:
1)我尝试将该方法直接暴露为WCF服务,但当然由于该方法而无效。
2)我尝试编译将要查找的字典,因为我不需要使用返回值进行anthing,我只需要更新缓存中的项目。但这也不起作用。我得到错误:无法转换类型为'System.Collections.Generic.Dictionary 2[System.Int32,CachingPrototype.CustomerQuickSearch]' to type 'System.Collections.Generic.Dictionary
2 [System.Int32,System.Object]'的对象。
您的评论非常有用,帮助我回答了我的问题。我想出的解决方案是简单地将我的WCF服务方法包装在switch语句中,这样我就可以使用正确的T类型调用UpdateCacheEntryItem方法。由于无法从Type转换为泛型T运算符,这是唯一的选择。由于我在Cache中没有那么多类型,因此效果很好。 (另一个解决方案是使用如下所述的接口,但不会像我希望的那样强类型。)
[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");
}
感谢大家的帮助,你们很棒!
答案 0 :(得分:10)
“动态声明变量”的想法与作为变量声明的一部分的类型的整体观点相反。这个想法是你可以告诉编译器类型,以便它可以检查你正在做什么。在这种情况下,您根本没有表达任何类型的信息。您也可以将myVar
声明为object
类型;这基本上与说“我对myVar
的价值几乎一无所知,除了它是一个参考。”
如果你有一个共同的界面当然,这将是伟大的 - 然后你可以安全地使用该界面的成员(当然,在创建/获取适当的实例之后)。但除此之外,除非你在编译时知道关于类型的某些东西,否则你真的没什么可做的。
在C#4中,您可以将变量声明为类型dynamic
,这将使所有绑定动态 - 基本上您可以使用它完成您喜欢的任何操作,并且它将在执行时解决。我建议尽可能使用静态类型,以便在编译时捕获错误。
答案 1 :(得分:2)
在我看来,界面和一些演员会解决你的问题。让每个可缓存的类实现一个接口。在您的字典中存储此类型的项目。据推测,CacheRef的类型为Dictionary<CacheKey,Dictionary<CacheKey,ICacheable>>
。剩下的就是确保可缓存的类实现接口。
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);
}
请注意,这不是,就像@Jon Skeet在他的回答评论中所说,强制执行词典中的类型。这取决于您的代码,以确保您将正确类型的对象放入每个缓存中。只要您的水合方法被单元测试所覆盖,我就会对此感到满意,以确保在给定特定键时,它们始终会生成相应类型的对象。